Promise 的出现为一直以来饱受“回调地狱”噩梦困扰的异步编程带来了希望,但一开始接触这个概念,理解起来难免有些困难。本文讲述了三种帮助理解 Promise 的方式。
引子
下面是一个调用基于 Promise 的函数 asyncFunc()
的例子:
|
|
所以呢,什么是 Promise?
- 概念上,调用
asyncFunc()
是一个阻塞式函数调用 - Promise 既是一个值的容器也是一个事件触发器
概念上:调用基于 Promise 的函数是阻塞的
|
|
main()
是一个异步函数。其函数体很好地从概念上表明发生了什么——也是我们通常如何看待异步运算:
- 行(A):等待,直到
asyncFunc()
执行完毕 - 行(B):打印
x
的结果值到控制台日志
在 ES6 和 Generator 之前,你不能暂停并重新恢复代码执行。这就是为什么,对于 Promise,要将恢复代码执行后所发生的一切都置于回调函数中。调用回调与恢复代码是相同的。
Promise 是异步传递的值的容器
如果一个函数返回一个 Promise,那么这个 Promise 就像一个空的容器,函数一旦运算完毕,最后就会向其中填充它的结果。你可以通过数组模拟此过程的简单版本:
|
|
使用 Promise,你不必通过 [0]
(像在行(A)中那样)访问最终值,你可以使用方法 then()
和回调函数。
Promise 是一个事件触发器
另一种看待 Promise 的方式是将其作为一个触发事件的对象。
|
|
注册事件监听器(行(B))可以在调用 asyncFunc()
之后完成,因为在这段代码完成后,交给 setTimeout()
(行(A))的回调是异步执行的。
典型的事件触发器专门用于传递多个事件,从你注册时开始。
相比之下,Promise 专门提供一个确定值,并提供内置保护以防止注册太晚:Promise 的结果被缓存并传递到在 Promise 状态确定后注册的事件侦听器。