You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何合并简化Ionic中API调用前重复的Promise检查逻辑?

解决Ionic API调用中重复检查网络和认证的问题

看起来你已经意识到了重复代码的困扰——每次API调用都嵌套网络和认证检查确实繁琐,后期维护也麻烦。下面我给你几个实用方案,既能浓缩重复逻辑,又能保留connCheck和authCheck的独立性,方便单独使用。

第一步:优化基础检查函数

先把原来的检查函数用async/await重构,让代码更简洁易读,避免手动创建Promise的冗余:

优化网络检查函数

如果你的Angular版本是15+,推荐用firstValueFrom替代已废弃的toPromise():

import { firstValueFrom } from 'rxjs';

async connCheck(): Promise<boolean> {
  try {
    // 发送心跳请求验证网络连通性
    await firstValueFrom(
      this.http.get(this.myURL() + '/heartbeat/', { responseType: 'text' })
    );
    return true;
  } catch (err) {
    // 请求失败说明无网络或服务器不可达
    return false;
  }
}

优化认证检查函数

用async/await简化逻辑,代码更直观:

async authCheck(message: string = 'Please login first!'): Promise<boolean> {
  const user = await this.storage.get('user');
  // 直接返回布尔值,简化判断逻辑
  return !!user;
}

第二步:组合检查逻辑(核心方案)

把两个检查逻辑封装成统一的准备函数,所有API调用都能复用,还能统一处理失败提示(比如Ionic Toast):

async prepareForApi(authMessage?: string): Promise<boolean> {
  // 先检查网络,没网就跳过认证检查,节省资源
  const hasNetwork = await this.connCheck();
  if (!hasNetwork) {
    // 弹出无网络提示
    const toast = await this.toastController.create({
      message: 'No internet connection available',
      duration: 2000,
      position: 'bottom'
    });
    await toast.present();
    return false;
  }

  // 网络正常,再检查认证状态
  const isAuthenticated = await this.authCheck(authMessage);
  if (!isAuthenticated) {
    // 弹出登录提示
    const toast = await this.toastController.create({
      message: authMessage || 'Please login first!',
      duration: 2000,
      position: 'bottom'
    });
    await toast.present();
    return false;
  }

  // 两项检查都通过
  return true;
}

第三步:简化API调用

现在有两种方式让你的API调用函数变得简洁:

方式一:用高阶函数包装API逻辑

创建一个包装函数,把检查逻辑和实际API调用解耦:

// 定义API调用的类型,方便类型提示
type ApiAction = () => Promise<any>;

async wrapApiCall(apiAction: ApiAction, authMessage?: string): Promise<any | null> {
  const canProceed = await this.prepareForApi(authMessage);
  if (!canProceed) {
    // 检查不通过,返回null或抛出错误(根据业务需求调整)
    return null;
  }
  // 执行实际的API调用
  return apiAction();
}

你的noteCreate函数可以简化成这样:

noteCreate(): Promise<any | null> {
  return this.wrapApiCall(async () => {
    // 只写实际的API请求逻辑
    return firstValueFrom(
      this.http.post(`${this.myURL()}/notes`, { title: 'New Note', content: 'Hello World' })
    );
  }, 'Please login to create a note!'); // 可选自定义认证提示
}

方式二:用TypeScript装饰器(更优雅)

如果项目启用了TypeScript装饰器(需在tsconfig.json开启experimentalDecorators和emitDecoratorMetadata),可以用装饰器自动给API方法添加检查逻辑:

首先定义装饰器:

function ApiCheck(authMessage: string = 'Please login first!') {
  return function(target: any, propertyKey: string, descriptor: PropertyDescriptor) {
    // 保存原方法的引用
    const originalMethod = descriptor.value;

    // 重写方法,注入检查逻辑
    descriptor.value = async function(...args: any[]) {
      const hasNetwork = await this.connCheck();
      if (!hasNetwork) {
        const toast = await this.toastController.create({
          message: 'No internet connection available',
          duration: 2000,
          position: 'bottom'
        });
        await toast.present();
        return null;
      }

      const isAuthenticated = await this.authCheck(authMessage);
      if (!isAuthenticated) {
        const toast = await this.toastController.create({
          message: authMessage,
          duration: 2000,
          position: 'bottom'
        });
        await toast.present();
        return null;
      }

      // 执行原API方法
      return originalMethod.apply(this, args);
    };

    return descriptor;
  };
}

给API方法添加装饰器即可:

@ApiCheck('Please login to create a note!')
async noteCreate(): Promise<any> {
  // 只写实际的API请求逻辑
  return firstValueFrom(
    this.http.post(`${this.myURL()}/notes`, { title: 'New Note', content: 'Hello World' })
  );
}

方案优势

  • 复用性:重复的检查逻辑集中在一处,后续修改规则(比如换网络验证方式、调整认证逻辑)只需改一个地方。
  • 独立性:connCheck和authCheck依然可以单独调用,满足“部分场景仅需单一检查”的需求。
  • 可读性:API方法只关注业务逻辑,代码更简洁,新人接手也更容易理解。

你可以根据项目习惯选择高阶函数或装饰器方案,两种都能很好地解决重复代码问题~

内容的提问来源于stack exchange,提问作者capcom-r

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.27 09:34:51