如何在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

