译者:骄阳
这篇博文用三种方式来理解 Promises.
这里asyncFunc()是一个调用基于Promise函数的示例:
function asyncFunc() {
return new Promise((resolve, reject) => {
setTimeout(() => resolve('DONE'), 100);
});
}
asyncFunc()
.then(x => console.log('Result: '+x));
// Output:
// Result: DONE
那么什么是Promise呢?
-
从概念上讲,调用
asyncFunc()是一个阻塞函数的调用. -
Promise 同时是一个值和一个事件触发器的容器.
从概念上: 调用一个基于Promise的函数是阻塞的
function asyncFunc() {
return new Promise((resolve, reject) => {
setTimeout(() => resolve('DONE'), 100);
});
}
async function main() {
const x = await asyncFunc(); // (A)
console.log('Result: '+x);
// Same as:
// asyncFunc()
// .then(x => console.log('Result: '+x));
}
main();
main() 是 一个异步函数. 它的函数体很好地从 概念上 表达发生了什么 - 我们通常如何看待异步计算:
-
行 (A): 等待,直到
asyncFunc()完成. -
行 (B): 之后打印它的结果
x.
在ECMAScript 6 和 generators 之前,不能挂起和继续代码,这是为什么,对于Promises,要把代码恢复后发生的一切放进回调函数里. 调用该回调函数与继续代码相同.
Promise 是一个异步传值的容器
如果一个函数返回Promise, 那么这个Promise就像一片空白,函数一旦计算完,将(通常)最终填充其结果。你可以通过一个数组模拟这个过程的一个简单版本:
function asyncFunc() {
const blank = [];
setTimeout(() => blank.push('DONE'), 100);
return blank;
}
const blank = asyncFunc();
// Wait until the value has been filled in
setTimeout(() => {
const x = blank[0]; // (A)
console.log('Result: '+x);
}, 200);
使用Promises, 不必通过[0]访问最终值(如行(A)),可以使用then()方法和回调函数。
Promise 是一个事件触发器
另一种查看Promise的方法是作为一个触发事件的对象。
function asyncFunc() {
const eventEmitter = { success: [] };
setTimeout(() => { // (A)
for (const handler of eventEmitter.success) {
handler('DONE');
}
}, 100);
return eventEmitter;
}
asyncFunc()
.success.push(x => console.log('Result: '+x)); // (B)
注册事件监听器(行(B))可以调用 asyncFunc()后完成,因为这段代码完成后,被传递给setTimeout() (行(A))的回调函数是异步执行的。
正常的事件触发器专门提供多个事件,一旦注册就开始执行。
相比之下,Promises专门提供一个值,并提供内置保护以防注册太晚:Promise的结果被缓存并传递给被注册后的事件监听器。
延展阅读
-
”Exploring ES6” 里的 “异步编程的Promises” 章
-
“Exploring ES2016 and ES2017”的 “异步函数”章
[](www.blogger.com/post-edit.g… ""Edit Post"")