Node.js中await未等待HTTPS POST请求返回结果的解决方法
问题:async函数中await未等待HTTPS请求响应就执行后续代码
编写了如下Node.js代码,其中async函数A通过https模块发起POST请求调用外部API,期望获取返回的token。但调用函数A时,await并未等待请求响应就执行了后续代码,导致无法获取预期的输出结果。当前调用let output = await A();时,无法获取到请求返回的token,代码直接执行了后续的console.log(output + 2);语句。请问如何修改代码,让函数A等待HTTPS请求响应返回后再执行后续逻辑?
原代码:
const https = require('https'); async function A() { let postData = JSON.stringify({ "f1": "D1", "f2": "D2", "encrypted": true }); let options = { hostname: "dummyurl1122.com", path: "/api/wow", method: "POST", timestamp: new Date(), headers: { 'Content-Type': 'application/json', } } let chunks = []; let reqGetToken = await https.request(options, (resGetToken) => { if (resGetToken.statusCode != 200) { console.log("***** Error = " + resGetToken.statusMessage); return; } resGetToken.on("data", (d) => { chunks.push(d); }); resGetToken.on("end", async () => { let output = JSON.parse(await (Buffer.concat(chunks)).toString()); return output.token; //****** I want this in output }); }); reqGetToken.on("error", (e) => { console.error(e); }); reqGetToken.write(postData); reqGetToken.end(); } let output = await A(); // I want the output but it does not waits for the https response console.log(output + 2);
问题原因
https.request是基于回调的API,它不返回Promise,所以await https.request(...)不会等待请求完成,函数A会直接执行到末尾返回undefined,导致后续代码提前执行。
修改方案
把https.request的逻辑包装成Promise,通过resolve返回token,reject抛出错误,让async函数能通过await正确等待请求完成:
const https = require('https'); async function A() { let postData = JSON.stringify({ "f1": "D1", "f2": "D2", "encrypted": true }); let options = { hostname: "dummyurl1122.com", path: "/api/wow", method: "POST", timestamp: new Date(), headers: { 'Content-Type': 'application/json', // 补充Content-Length头,多数API要求此参数解析请求体 'Content-Length': Buffer.byteLength(postData) } } // 将请求逻辑封装为Promise return new Promise((resolve, reject) => { let chunks = []; const reqGetToken = https.request(options, (resGetToken) => { if (resGetToken.statusCode !== 200) { const errorMsg = `请求错误:${resGetToken.statusMessage}`; console.log("***** Error = " + errorMsg); // 非200状态码时抛出错误 reject(new Error(errorMsg)); return; } resGetToken.on("data", (d) => { chunks.push(d); }); resGetToken.on("end", () => { try { // Buffer.concat和toString都是同步操作,无需await const responseStr = Buffer.concat(chunks).toString(); const output = JSON.parse(responseStr); // 成功获取token后返回结果 resolve(output.token); } catch (parseError) { // 处理JSON解析失败的情况 console.error("JSON解析错误:", parseError); reject(parseError); } }); }); reqGetToken.on("error", (e) => { console.error("请求发送错误:", e); reject(e); }); reqGetToken.write(postData); reqGetToken.end(); }); } // 全局await需包裹在async立即执行函数中(兼容CommonJS模块) (async () => { try { let output = await A(); console.log(output + 2); } catch (err) { console.error("获取token失败:", err); } })();
关键修改点
- 用Promise封装
https.request逻辑,通过resolve传递最终token,reject处理各类错误(请求错误、非200状态码、JSON解析错误)。 - 移除原代码中多余的
await (Buffer.concat(chunks)).toString(),因为相关操作都是同步的。 - 补充
Content-Length请求头,确保服务器能正确解析POST请求体。 - 将全局
await A()包裹在async立即执行函数中,避免Node.js环境下的顶级await兼容性问题。 - 添加全局错误捕获,避免未处理的Promise rejection。
内容的提问来源于stack exchange,提问作者Vishal Gupta
相关产品推荐
相关产品推荐

