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

如何仅在特定函数执行完成后返回响应?Promise实现失败求助

如何确保异步请求完成后再返回响应?

首先得指出你原来代码的核心问题:request是回调式的异步操作,你在循环发起请求后立刻就调用了resolve(resp),这时候所有请求还没执行完,resp里的数据根本没被填充,所以Promise提前完成了,自然得不到正确结果。而且原代码里如果某个请求返回空数据,直接发送204响应还会导致后续请求回调执行时重复发送响应,引发错误。

下面给你两种可行的实现方式,都是基于Promise来正确等待所有异步请求完成:


方法一:用Promise封装请求 + Promise.all

首先把单个request调用封装成Promise,这样就能用Promise.all来等待所有请求完成:

// 封装单个deal的请求为Promise
function fetchDeal(dealId, auth) {
  return new Promise((resolve, reject) => {
    const link = `https://api.cortellis.com/api-ws/ws/rs/deals-v2/deal/${dealId}?fmt=json`;
    const options = {
      method: 'GET',
      uri: link,
      auth: auth,
    };
    
    request(options, function(error, response, body) {
      if (error) {
        reject(error); // 请求失败时抛出错误
        return;
      }
      
      const bodyData = JSON.parse(body).dealRecordOutput;
      if (bodyData.length === 0) {
        resolve(null); // 空数据时返回null,后续统一处理
      } else {
        // 只返回需要的字段,简化后续处理
        resolve({
          type: bodyData.Type,
          status: bodyData.Status
        });
      }
    });
  });
}

// 生成所有请求的Promise数组
const dealPromises = deals.map(dealId => fetchDeal(dealId, auth));

// 等待所有请求完成
Promise.all(dealPromises)
  .then(results => {
    // 过滤掉空数据的结果
    const validResults = results.filter(result => result !== null);
    
    // 如果所有结果都是空的,返回204
    if (validResults.length === 0) {
      return res.status(204).json({ data: [] });
    }
    
    // 整理成需要的响应格式
    const resp = {
      type: validResults.map(r => r.type),
      status: validResults.map(r => r.status)
    };
    
    res.status(200).json({ data: resp });
  })
  .catch(error => {
    // 处理请求中的错误(比如网络问题、API报错)
    res.status(500).json({ error: '处理请求时发生错误' });
    next(error);
  });

方法二:用async/await简化代码

如果你的环境支持ES8+,用async/await可以让代码更易读,逻辑更清晰:

// 同样先封装单个请求的Promise
function fetchDeal(dealId, auth) {
  return new Promise((resolve, reject) => {
    const link = `https://api.cortellis.com/api-ws/ws/rs/deals-v2/deal/${dealId}?fmt=json`;
    const options = {
      method: 'GET',
      uri: link,
      auth: auth,
    };
    
    request(options, function(error, response, body) {
      if (error) {
        reject(error);
        return;
      }
      
      const bodyData = JSON.parse(body).dealRecordOutput;
      if (bodyData.length === 0) {
        resolve(null);
      } else {
        resolve({
          type: bodyData.Type,
          status: bodyData.Status
        });
      }
    });
  });
}

// 用async函数处理所有请求
async function handleDealsRequest() {
  try {
    const dealPromises = deals.map(dealId => fetchDeal(dealId, auth));
    const results = await Promise.all(dealPromises);
    
    const validResults = results.filter(result => result !== null);
    
    if (validResults.length === 0) {
      return res.status(204).json({ data: [] });
    }
    
    const resp = {
      type: validResults.map(r => r.type),
      status: validResults.map(r => r.status)
    };
    
    res.status(200).json({ data: resp });
  } catch (error) {
    res.status(500).json({ error: '处理请求时发生错误' });
    next(error);
  }
}

// 执行函数
handleDealsRequest();

关键改进点说明:

  1. 避免提前resolve:通过Promise.all等待所有异步请求完成后再处理结果,确保resp里的数据是完整的。
  2. 统一处理空数据:不再在单个请求回调里直接发送响应,而是等所有请求完成后判断是否有有效数据,避免重复发送响应导致的错误。
  3. 错误处理:通过catch捕获请求过程中的错误,统一返回500响应,避免程序崩溃。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.27 07:32:57