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

如何在Promise内使用await?解决异步执行器报错问题

问题整理

背景

原本发起服务器请求无需添加await,后续服务器要求所有请求必须携带token,需修改现有代码适配新要求。

初始代码

export const countries = (data: IData) => {
  const countryRequests = getRequests(data)
  const countryResponse = countryRequests?.reduce((countryResponse, request) => {
    const countryResponses = new Promise((resolve, reject) => {
      instance
        .post(`/country`, request)
        .then(data => {
          resolve(data)
        })
        .catch(err => {
          reject(err)
        })
    })

    return [...countryResponse, countryResponses]
  }, [])


  return countryResponse
}

错误修改尝试

为在请求前添加token,尝试在Promise回调中加入async调用await addAccessToken(),修改后代码:

export const countries = (data: IData) => {
  const countryRequests = getRequests(data)
  const countryResponse = countryRequests?.reduce((countryResponse, request) => {
    const countryResponses = new Promise(async (resolve, reject) => { // 此处添加async
    await addAccessToken() // 请求前添加token到header
      instance
        .post(`/country`, request)
        .then(data => {
          resolve(data)
        })
        .catch(err => {
          reject(err)
        })
    })

    return [...countryResponse, countryResponses]
  }, [])


  return countryResponse
}

addAccessToken函数代码:

export const addAccessToken = async () => {
  const accessToken = await instance.get<IAccessToken>(
    '/access_token'
  )
  const { access_token } = accessToken.data
  instance.defaults.headers.common['Authorization'] = `Be ${access_token}`
}

此时触发ESLint错误:Promise executor functions should not be async.(no-async-promise-executor),需解决该错误。

后续修改及疑问

之后调整代码,将countries改为异步函数并提前调用await addAccessToken():

export const countries = async (data: IData) => {
  const countryRequests = getRequests(data)
  await addAccessToken()

  const countryResponse = countryRequests?.reduce((countryResponse, request) => {
    const countryResponses = instance
      .post(`/country`, request)  // 疑问:此处请求成功时,是否等价于原代码中的resolve(data)?
      .catch(err => {
        console.error(err)
      })
    return [...countryResponse, countryResponses]
  }, [])

 
  return countryResponse
}

同时添加Promise.all处理请求数组:

const countryResponses = countries(data)

// 处理接口1返回内容
Promise.all([...countryResponses])
  .then(values => {
    const countryResponsesResult = values.map((value, _index) => {
      return value.data.result ? value.data.result : []
    })
   
    // 更新接口1内容
    props.setProjection({
      kind: 'success',
      payload: {
        data: countryResponsesResult,
      },
    })
  })
  .catch(_error => {
    // 更新接口1错误状态
    props.setProjection({
      kind: 'fail',
      payload: {
        error: new Error(_error.message),
      },
    })
  })

需确认:instance.post调用成功时,是否等价于原代码中的resolve(data)?


解答

1. 解决no-async-promise-executor错误

ESLint提示该错误的核心原因:Promise的执行器函数如果设为async,会自动返回一个Promise,但这个返回值会被Promise构造器忽略;同时执行器内部抛出的错误会被async函数的Promise捕获,无法触发构造器的reject,容易导致未处理的Promise拒绝。

你后续修改的方向是对的,正确的优化方式:

  • 不需要手动封装新的Promise,instance.post本身就返回Promise,直接复用即可。
  • addAccessToken只需调用一次,因为instance.defaults.headers是全局配置,设置后所有后续请求都会携带该header,无需每个请求前重复调用。

2. 关于instance.post是否等价于原代码中的resolve(data)

完全等价。

原代码手动封装Promise的逻辑是:instance.post成功时调用resolve(data),失败时调用reject(err);而instance.post本身返回的Promise,请求成功时会自动resolve请求返回的data,失败时会自动reject对应的错误,和手动封装的逻辑完全一致。

不过注意你后续代码中给instance.post加了.catch(err => console.error(err)),这会导致该Promise永远处于resolved状态(catch会捕获错误并返回resolved的Promise),外层Promise.all无法感知请求失败,建议去掉内部catch,把错误处理放在外层Promise.all的catch中,才能正确触发失败回调。

优化后的countries函数:

export const countries = async (data: IData) => {
  const countryRequests = getRequests(data)
  // 全局设置一次token即可
  await addAccessToken()

  // 直接映射生成请求Promise数组,无需冗余封装
  return countryRequests?.map(request => instance.post(`/country`, request)) || []
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.11 02:35:35