为何函数未等待异步函数执行完成?TS代码问题排查
TypeScript异步请求执行顺序问题修复
问题说明
当前代码中getInfo函数调用apicall后,未等待API请求完成就输出APIres,导致结果为undefined,执行顺序不符合预期。
原代码
var APIres: any; export class Component implements OnInit { async getInfo(){ await this.apicall(); console.log('API response', APIres) } async apicall(){ var request = new XMLHttpRequest(); request.open('POST', 'URL', true); request.setRequestHeader('Content-Type', 'application/json'); request.setRequestHeader('Authorization', 'Bearer ' + accessToken); request.onreadystatechange = async function () { console.log('Got Values') await res(JSON.parse(this.responseText)); } request.send(content); } } async function res(x){console.log('out');APIres = x} //Outside of export
当前输出
API response undefined Got Values out
期望输出
Got Values out API response res
问题根源
apicall虽标记为async,但并未真正等待异步请求完成:
XMLHttpRequest是基于回调的异步API,onreadystatechange属于事件回调,await无法作用于该逻辑apicall函数发送请求后立即返回,导致getInfo中的await直接执行后续代码
修改方案
将apicall包装为返回Promise的函数,让await能真正等待请求完成;同时移除全局变量,直接通过Promise传递结果,避免全局状态带来的问题:
修改后的代码
export class Component implements OnInit { async getInfo(){ const apiRes = await this.apicall(); console.log('API response', apiRes) } apicall(): Promise<any> { return new Promise((resolve, reject) => { const request = new XMLHttpRequest(); request.open('POST', 'URL', true); request.setRequestHeader('Content-Type', 'application/json'); request.setRequestHeader('Authorization', 'Bearer ' + accessToken); request.onreadystatechange = async function () { if (this.readyState === XMLHttpRequest.DONE) { console.log('Got Values') const responseData = JSON.parse(this.responseText); await res(responseData); resolve(responseData); // 请求完成后传递结果 } }; request.onerror = function() { reject(new Error('Request failed')); // 处理请求错误 }; request.send(content); }); } } async function res(x){console.log('out');} // 无需全局变量,移除赋值逻辑
关键修改点
- 用Promise包裹XMLHttpRequest:让
apicall返回Promise,在请求完成(readyState === 4)时调用resolve传递响应数据,请求失败时调用reject处理错误 - 移除全局变量
APIres:直接通过Promise返回结果,在getInfo中接收后使用,避免全局状态的不可预测性 - 完善错误处理:新增
onerror回调处理请求失败场景,增强代码健壮性
修改后,getInfo中的await this.apicall()会等待API请求完成并处理完res函数后,才执行后续的console.log,执行顺序完全符合预期。
内容的提问来源于stack exchange,提问作者R. Baraiya
相关产品推荐
相关产品推荐

