这里发生了什么
首先解释一下这里发生了什么。当你做这样的事情时:
var info = new Promise((resolve, reject) => {
// ...
}).then(result => {
// ...
}).catch(err => {
// ...
});
那么info 变量的值最终是一个承诺。那是因为你从new Promise()构造函数返回的promise开始,你调用它的.then()方法返回第二个promise,然后在第二个promise上你调用.catch()方法返回第三个promise——这第三个promise是保存到info 变量中的内容。
所有这些方法调用都会在原始 HTTP 请求完成之前立即返回,因此当您到达下一行时:
console.log(info);
不可能访问来自request() 调用的响应值,因为它还没有发生(此时还没有调用request() 回调)。 info 变量有一个 promise,它是一个对象,您可以使用它来注册您希望在值最终可用时运行的回调。当您将它传递给 console.log() 时,它会打印出这是一个承诺。
如何获取价值
现在,当您想在该值最终可用时打印该值,您可以将一个 Promise 解析回调附加到您拥有的 Promise 中,例如用这样的代码:
info.then((value) => {
// you can use the value here
console.log('Value:', value);
}).catch((err) => {
// the promise got rejected
console.log('Error:', err);
});
如果您使用的是相对较新的 Node (7.0+) 版本,那么如果您位于使用 async 关键字声明的函数内部,则可以使用 await 来获取 Promise 的分辨率值,如下所示:
(async function () {
let value = await info;
console.log(value);
})();
或更短:
(async () => {
console.log(await info);
})();
(如果您已经在 async 函数中,则不需要 (async () => { ... })(); 包装器。)
工作原理
await 关键字的作用是它从一个隐式生成器函数产生承诺,该函数将控制权传递给外部协程控制代码,该代码将解析和拒绝处理程序附加到产生的承诺并通过返回来自 await 运算符的解析值,或者如果 promise 被拒绝则引发异常。然后生成器可以继续使用返回值并捕获异常,或者它可以让异常冒泡到外部块,在那里它可以被捕获或转换为拒绝 async 函数返回的隐式承诺,如果不一起处理路。
如何使用它
这可能看起来很复杂,但从您的代码的角度来看,它可以让您执行以下操作:
let value = await fun();
(其中fun() 是一个返回promise 的函数)并在value 变量中提供promise 的解析值(实际值,而不是promise)。
请记住,当相关的承诺被拒绝时,await 关键字会引发异常。要处理这种情况,您可以使用 try/catch 块:
try {
let value = await fun();
// promise got resolved, you have value here:
console.log('Value:', value);
} catch (error) {
// promise got rejected, you have error here:
console.log('Error:', error);
}
相当于没有新语法的这段代码:
fun().then((value) => {
// promise got resolved, you have value here:
console.log('Value:', value);
}).catch((error) => {
// promise got rejected, you have error here:
console.log('Error:', error);
});
主要区别在于当您 await 在单个 try 块中处理多个承诺时,变量范围与使用多个链接的 .then() 处理程序不同,每个处理程序都返回一个新的承诺。
您的代码看起来使用了await,但实际上没有
我添加了如何使用await 修复代码的示例,因为您编写代码的方式如下:
var info = new Promise(...);
// here the 'info' variable is set to a promise
真的是这样的:
var info = await new Promise(...);
// here the 'info' variable is set to the value
// that the promise eventually resolves to
更多信息
有关详细信息,请参阅:
节点支持
有关 Node 版本中对该语法的支持,请参阅:
在你没有原生支持 async 和 await 的地方你可以使用 Babel:
或者在语法稍有不同的情况下使用基于生成器的方法,例如 co 或 Bluebird 协程: