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

未声明async但含Promise的函数能否用await?代码优化方案咨询

解决await对sqlUpsertRecommendations无效果的问题

问题根源

VSCode提示“'await' has no effect on the type of this expression”,核心原因是sqlUpsertRecommendations函数没有返回内部创建的Promise实例。函数里新建了Promise但没通过return导出,导致函数默认返回undefined,await undefined自然不会产生异步等待的效果。

第一步:修复Promise返回问题

先给函数加上return,让它返回Promise实例:

const sqlUpsertRecommendations = recommendationsArray => {
  // eslint-disable-next-line no-new
  return new Promise(resolve => { // 新增return
    const insertStatus = {
      .... // 原状态定义
    };
    // 原函数剩余逻辑...
  });
};

原代码的其他严重问题(必须修复)

仅返回Promise还不够,原函数的逻辑存在异步管理错误:

  1. 提前resolve:循环中第一个txn.executeSql成功就会调用resolve,后续的SQL操作还没执行就直接结束了Promise,导致只有第一条数据被处理。
  2. 错误处理混乱:错误时仅在最后一条数据处理完才resolve,中间错误无法被捕获;而且错误时用resolve返回错误信息,不符合Promise的规范(应该用reject传递错误)。

优化后的完整代码

以下是修复了异步管理和错误处理的版本:

const sqlUpsertRecommendations = recommendationsArray => {
  return new Promise((resolve, reject) => {
    const insertStatus = {
      inserted: 0,
      notInserted: 0,
      arrayEmpty: true
    };

    // 空数组直接返回
    if (recommendationsArray.length === 0) {
      resolve({
        error: false,
        results: insertStatus,
        localMessage: 'recommendationsArray.length = 0',
      });
      return;
    }

    insertStatus.arrayEmpty = false;

    // 开启事务
    dbConfig.transaction(
      txn => {
        // 把每条SQL操作包装成Promise并收集
        const sqlTasks = recommendationsArray.map(item => {
          const {
            id, recommendation_attribute, recommendation_value,
            segment_id, target_attribute, target_value,
            is_deleted, updated_at, name, image, border_color
          } = item;

          const params = [
            id, recommendation_attribute, recommendation_value,
            segment_id, target_attribute, target_value,
            is_deleted, updated_at, name, image, border_color
          ];

          return new Promise((taskResolve, taskReject) => {
            txn.executeSql(
              upsertRecommendations,
              params,
              () => {
                insertStatus.inserted += 1;
                taskResolve();
              },
              error => {
                insertStatus.notInserted += 1;
                crashlytics().recordError(error);
                __DEV__ && console.log('sqlUpsertRecommendations error:', error);
                // 这里如果需要某条失败就终止,直接taskReject;如果要继续执行所有任务,就taskResolve
                taskReject(error);
              }
            );
          });
        });

        // 等待所有SQL任务完成:用allSettled会统计所有结果,用all则任意失败就终止
        Promise.allSettled(sqlTasks)
          .then(() => resolve({ error: false, results: insertStatus }))
          .catch(error => reject({ error: true, message: error.message, results: insertStatus }));
      },
      // 事务本身的错误处理
      transactionError => {
        crashlytics().recordError(transactionError);
        reject({ error: true, message: transactionError.message, results: insertStatus });
      }
    );
  });
};

正确使用await的方式

现在可以配合try/catch正常使用await:

const testFunction = async () => { 
  try {
    const upsertResult = await sqlUpsertRecommendations(parsedData);
    console.log('批量插入完成:', upsertResult);
    // 处理成功逻辑,比如更新UI或上报统计
  } catch (err) {
    console.error('批量插入失败:', err);
    // 处理错误逻辑,比如提示用户或重试
  }
};

核心要点总结

  • 要让await生效,异步函数必须返回Promise实例。
  • 批量异步操作需统一管理完成时机,避免提前resolve导致逻辑不完整。
  • 错误处理遵循Promise规范:用reject传递错误,配合try/catch捕获异常。

内容的提问来源于stack exchange,提问作者gpbaculio

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.19 19:40:20