深入理解Promise

Promise 的含义

Promise 是异步编程的一种解决方案。它最早由社区提出并实现,ES6 将它写入了标准,提供原生 Promise对象成为统一标准。 可以把 Promise 理解成一个容器,里面存放了一个未来才会结束的事件(通常是异步操作)的结果。从语法上说,Promise 是一个对象,它提供统一的 API,可以获取异步操作的结果。 Promise 有两个特点:

  1. 对象的状态不受外界影响。Promise 对象代表一个异步操作,有三种状态:pending(进行中)、fulfilled(已成功)和rejected(已失败)。只有异步操作的结果可以决定当前是哪一种状态,其他任何操作都无法改变这个状态。
  2. 一旦状态改变,就不会再变,任何时候都可以得到这个结果。Promise 对象的状态改变只有两种可能:从pending变成fulfilled和从pending变成rejected。只要这两种情况发生,状态就冻结了,不会再变了。

如果 Promise 返回了成功的信息,那么你在绑在定成功事件上的回调就会得到这个消息。 如果发生了错误,你绑定在错误事件上的回调或捕获错误的回调会得到这个信息。

Promise 解决了什么问题

首先我个人并不认为 Promise 的出现彻底解决了"回调地狱"的问题,因为 Promise 并没有移除回调函数。 那 Promise 究竟解决了什么问题呢?我们不妨先回想下,在 Promise 出现之前,我们通过回调函数控制异步流程的方式是怎么样的。用 axios 举例:

$.axios({
	method: 'GET',
	url: '/xxx',
	success: function (res) {
		...
	}
})

上面我们使用 axios 发送一个 get 请求,通过 success 字段定义了该请求成功之后的回调函数,试问如果你从没有使用过 axios,你知道请求失败的回调函数要怎么注册吗? 其实这就是我想表达的程序的控制权问题,在 Promise 出现之前,通常是由第三方库传递回调来转移控制权的,你需要根据第三方库的规则去注册回调函数,如果你的项目引入了多个第三方库,而这几个第三方库的定义又不同时,这其实就造成了阅读可维护性上的障碍。 而 Promise 的出现则解决了上述的问题,并且 Promise 被写入了标准,更加安全可靠。这是 JavaScript 种异步流程控制表达上一个很大的进步。

Promise 的缺点

  1. 无法取消 Promise,一旦新建它就会立即执行,无法中途取消。
  2. 如果不设置回调函数 Promise 内部抛出的错误,不会反应到外部。
  3. 当处于 pending 状态时,无法得知目前进展到哪一个阶段(是刚开始还是即将完成)。