将返回Promise的函数转为async/await后,如何返回响应体?
问题:Promise转async/await后无法返回响应体?
我正尝试将一个返回Promise的函数转换为使用async/await的形式(我了解async函数会隐式返回Promise)。该函数封装了对https.request的调用,原Promise函数通过resolve(body)返回响应体且运行正常。但转为async/await形式后,我无法找到返回响应体的方法,请问我遗漏了什么?
原Promise函数代码
promise_it = (data) => { // throws FATAL if (!data) {throw new Error('data is missing');} return new Promise((resolve, reject) => { let postData = JSON.stringify(data); let options = { hostname: 'httpbin.org', port: 443, path: '/post', method: 'POST', headers: { // 'Content-Type': 'application/json', // Accept: 'application/json' 'Content-Type': 'application/x-www-form-urlencoded', 'Content-Length': postData.length } }; const https = require('https'); let req = https.request(options, (res) => { let body = []; res.on('data', function(chunk) { body.push(chunk); }); res.on('end', function() { try { body = JSON.parse(Buffer.concat(body).toString()); } catch(e) { console.error(e.message) reject(e); } resolve(body); }); }); req.on('error', (e) => { console.error(e); reject(e) }); req.write(postData); req.end(); }); } try { data = {firstName: 'Donald', lastName: 'Duck'} const who = promise_it(data) who .then(r => console.info('INFO:',r)) .catch(e => console.error('ERROR:',e)); } catch (error) { console.error('FATAL:',error) }
改写后的async/await函数代码
async_it = async (data) => { if (!data) {throw new Error('data is missing');} let postData = JSON.stringify(data); let options = { hostname: 'httpbin.org', port: 443, path: '/post', method: 'POST', headers: { // 'Content-Type': 'application/json', // Accept: 'application/json' 'Content-Type': 'application/x-www-form-urlencoded', 'Content-Length': postData.length } }; const https = require('https'); let req = https.request(options, (res) => { let body = []; res.on('data', function(chunk) { body.push(chunk); }); res.on('end', function() { try { body = JSON.parse(Buffer.concat(body).toString()); // how do i return the body? } catch(e) { console.error('HERE:',e.message) throw e; } }); }); req.on('error', (e) => { console.error('THERE:',e.message) }); req.write(postData); req.end(); } (async () => { try { data = {firstName: 'Donald', lastName: 'Duck'} const who = await async_it(data) console.info('INFO:',who) } catch (error) { console.error('FATAL:',error) } })();
解决方案
核心问题是:async/await只是Promise的语法糖,无法直接处理回调式异步API。你之前的改写没有把https.request的异步逻辑包裹进Promise,导致async函数执行完同步代码就直接返回了一个空的Promise,自然拿不到响应体。
修正后的代码需要将整个https.request逻辑封装进Promise,再在async函数中返回这个Promise,这样await就能捕获到resolve的结果:
async_it = async (data) => { if (!data) {throw new Error('data is missing');} let postData = JSON.stringify(data); let options = { hostname: 'httpbin.org', port: 443, path: '/post', method: 'POST', headers: { 'Content-Type': 'application/x-www-form-urlencoded', 'Content-Length': postData.length } }; const https = require('https'); // 将请求逻辑封装进Promise return new Promise((resolve, reject) => { let req = https.request(options, (res) => { let body = []; res.on('data', function(chunk) { body.push(chunk); }); res.on('end', function() { try { body = JSON.parse(Buffer.concat(body).toString()); resolve(body); // 成功时传递响应体 } catch(e) { console.error('HERE:',e.message); reject(e); // 解析失败时抛出错误 } }); }); req.on('error', (e) => { console.error('THERE:',e.message); reject(e); // 请求错误时抛出错误 }); req.write(postData); req.end(); }); } (async () => { try { data = {firstName: 'Donald', lastName: 'Duck'} const who = await async_it(data); console.info('INFO:',who); } catch (error) { console.error('FATAL:',error); } })();
关键说明
- 对于Node.js中这类回调式的异步API(比如
https.request、fs.readFile等),必须先通过new Promise进行Promise化,才能用async/await语法处理。 - async函数内部通过return这个Promise,让外部的await可以等待异步操作完成,并获取resolve的结果;所有错误(请求错误、JSON解析错误)通过reject抛出,会被外层的try/catch捕获。
- 你之前在回调中
throw e不会被async函数的try/catch捕获,因为回调是异步执行的,不属于当前async函数的同步执行上下文,必须通过reject传递错误。
内容的提问来源于stack exchange,提问作者craig
相关产品推荐
相关产品推荐

