如何在Promise内部实现代码等待获取异步返回值?
问题根因
await 关键字仅允许在 async 声明的异步函数内部使用,你当前写await的位置是request的普通匿名回调函数内,该函数未被标记为async,属于语法错误,无法正常执行。
除了await使用位置的问题,原代码还有几个隐性逻辑bug:
- 请求报错分支执行
reject后没有阻断后续逻辑,会出现已拒绝Promise后又尝试执行resolve的冲突 - 无关联联系人的分支执行
resolve(null)后同样没有阻断,后续会执行到末尾的resolve(contacBID),此时contacBID未定义,会覆盖之前的resolve结果 - 没有对
JSON.parse、异步联系人查询操作做异常捕获,一旦解析失败或者查询报错,会导致Promise永远悬停,不会进入reject分支
修复方案
最小改动方案
不需要调整整体结构,只需要给request的回调函数加上async标记,补全分支阻断和异常捕获即可,完全兼容你现有返回Promise的调用要求:
const optionsA = { method: "GET", url: "https://example.com", qs: { hapikey: "smthng" } }; return new Promise(function(resolve, reject){ // 给回调加async标记,内部即可合法使用await request(optionsA, async function (error, response, body) { if(error){ logResponse("could not reach boondmanager status:", response.statusCode); reject("error while reading"); // 阻断后续逻辑执行 return; } try { const dealH = JSON.parse(body); const associatedVids = dealH?.associations?.associatedVids; // 无关联联系人直接返回 if(!associatedVids || associatedVids[0] === undefined){ console.log("Not linked at all with a contact") resolve(null); return; } const ContactHID = associatedVids[0]; // 此处await会等待异步操作执行完成,拿到最终结果而非Promise对象 const contacBID = await ContactIDFinder.findingBoondIDcontact(ContactHID); console.log(`attempt at finding the BID for the contact linked to the company led to : ${contacBID}`); if (contacBID != null) { console.log("associated BID is : "+ contacBID) } else { console.log("linked with a contact unsynchronized") } resolve(contacBID); } catch(err) { // 捕获JSON解析、异步查询的所有异常,统一走reject逻辑 reject(err); } }); });
更规范的重构方案
回调嵌套的写法可读性和可维护性较差,可以先把回调风格的request封装为通用Promise工具函数,全程用async/await平铺写逻辑,最终返回值依然是Promise,和你后续的调用逻辑完全适配:
// 先把request封装为通用Promise请求方法 function requestPromise(options) { return new Promise((resolve, reject) => { request(options, (error, response, body) => { if (error) { logResponse("could not reach boondmanager status:", response.statusCode); reject("error while reading"); return; } resolve({response, body}); }) }) } // 外层标记为async,内部可直接使用await async function getLinkedContactBoondID() { const optionsA = { method: "GET", url: "https://example.com", qs: { hapikey: "smthng" } }; try { const { body } = await requestPromise(optionsA); const dealH = JSON.parse(body); const associatedVids = dealH?.associations?.associatedVids; if(!associatedVids || associatedVids[0] === undefined){ console.log("Not linked at all with a contact") return null; } const ContactHID = associatedVids[0]; const contacBID = await ContactIDFinder.findingBoondIDcontact(ContactHID); console.log(`attempt at finding the BID for the contact linked to the company led to : ${contacBID}`); if (contacBID != null) { console.log("associated BID is : "+ contacBID) } else { console.log("linked with a contact unsynchronized") } // async函数的返回值会自动包装为Promise,和原逻辑完全兼容 return contacBID; } catch(err) { throw err; } } // 后续调用既可以用.then()链式调用,也可以在async函数里用await拿结果 // getLinkedContactBoondID().then(res => { /* 你的后续逻辑 */ })
提示:你当前使用的
requestnpm包已经官方停止维护,如果是新项目可以直接替换为原生fetch、axios等原生支持Promise的请求库,省去手动封装Promise的步骤。
内容的提问来源于stack exchange,提问作者Louis Tonnevy
相关产品推荐
相关产品推荐

