关于Promise引起的一些思考

76 阅读5分钟

1、我们首先来简单概括下Promise

Promise是ES6新增的语法,解决了回调地狱的问题。 无论是ES6的Promise也好,JQuery的Promise也好,不同的库有不同的实现方式,但是大家遵守的都是同一套规范,所以,Promise并不指特定的某个实现,他是一种规范,是一套处理JavaScript异步的机制。 Promise本质上就是一个绑定了回调的对象,而不是将回调传回函数内部。 所以,Promise在一定程度上解决了回调函数的书写结构问题,但回调函数依然在主流程上存在,只不过都都放到了then(...)里面。

2、我们再来说一下Promise相关规范

  • 我们把Promise看成一个状态机。初始状态是pending状态,可以通过函数resolve和reject,将状态转变为resolved或者rejected状态,状态一旦改变就不能再次变化。
  • then函数会返回一个Promise实例,并且返回值是一个新的实例而不是之前的实例。因为Promise规范规定除了pending状态,其他状态是不可变的,如果返回的是一个相同实例的话,多个then调用就失去意义了。
  • then方法可以被同一个Promise调用多次
  • 值穿透

3、Promise是如何实现的?

  1. Promise的简单实现

image.png

2、Promise的大致框架

大致框架有了,但是Promise状态,resolve函数,reject函数,以及then等回调没有详细处理

image.png

3、Promise的链式存储

我们先看一个例子:

image.png 每间隔1秒打印一个数字,哈哈,这个不是真实的间隔1秒,汪汪,

这个的输出是啥?

打印顺序:1、2、3

这里我们能确认的是:

  • 让a,b,c的只能在then的回调接收到
  • 在连续的异步调用中,如何保证异步函数的执行顺序

Promise一个常见的需求就是连续执行两个或者多个异步操作,这种情况下,每一个后来的操作都在前面的操作执行成功之后,带着上一步操作所返回的结果开始执行。这里用setTimeout来处理.

image.png

4、Promise的状态机制和执行顺序

为了保证Promise的异步操作时的顺序执行,这里给Promise加上状态机制

image.png

5、Promise的递归执行

每个Promise后面链接一个对象,该对象包含onresolved,onrejected,子promise三个属性.

当父Promise 状态改变完毕,执行完相应的onresolved/onrejected的时候,拿到子promise,在等待这个子promise状态改变,在执行相应的onresolved/onrejected。依次循环直到当前promise没有子promise。

image.png

6、Promise的异常处理

每个Promise后面链接一个对象,该对象包含onresolved,onrejected,子promise三个属性.

当父Promise 状态改变完毕,执行完相应的onresolved/onrejected的时候,拿到子promise,在等待这个子promise状态改变,在执行相应的onresolved/onrejected。依次循环直到当前promise没有子promise。

image.png

7、Promise的then的实现

then 方法是 Promise 的核心,这里做一下详细介绍。

promise.then(onFulfilled, onRejected)

一个 Promise 的then接受两个参数: onFulfilled和onRejected(都是可选参数,并且为函数,若不是函数将被忽略)

  • onFulfilled 特性:

当 Promise 执行结束后其必须被调用,其第一个参数为 promise 的终值,也就是 resolve 传过来的值
在 Promise 执行结束前不可被调用
其调用次数不可超过一次

  • onRejected 特性

当 Promise 被拒绝执行后其必须被调用,第一个参数为 Promise 的拒绝原因,也就是reject传过来的值
在 Promise 执行结束前不可被调用
其调用次数不可超过一次

  • 调用时机

onFulfilled 和 onRejected 只有在执行环境堆栈仅包含平台代码时才可被调用(平台代码指引擎、环境以及 promise 的实施代码)

  • 调用要求

onFulfilled 和 onRejected 必须被作为函数调用(即没有 this 值,在 严格模式(strict) 中,函数 this 的值为 undefined ;在非严格模式中其为全局对象。)

  • 多次调用

then 方法可以被同一个 promise 调用多次

当 promise 成功执行时,所有 onFulfilled 需按照其注册顺序依次回调
当 promise 被拒绝执行时,所有的 onRejected 需按照其注册顺序依次回调

  • 返回

then方法会返回一个Promise,关于这一点,Promise/A+标准并没有要求返回的这个Promise是一个新的对象,但在Promise/A标准中,明确规定了then要返回一个新的对象,目前的Promise实现中then几乎都是返回一个新的Promise(详情)对象,所以在我们的实现中,也让then返回一个新的Promise对象。

promise2 = promise1.then(onFulfilled, onRejected);
  • 如果 onFulfilled 或者 onRejected 返回一个值 x ,则运行下面的 Promise 解决过程:[[Resolve]](promise2, x)
  • 如果 onFulfilled 或者 onRejected 抛出一个异常 e ,则 promise2 必须拒绝执行,并返回拒因 e
  • 如果 onFulfilled 不是函数且 promise1 成功执行, promise2 必须成功执行并返回相同的值
  • 如果 onRejected 不是函数且 promise1 拒绝执行, promise2 必须拒绝执行并返回相同的拒因

不论 promise1 被 reject 还是被 resolve , promise2 都会被 resolve,只有出现异常时才会被 rejected。

每个Promise对象都可以在其上多次调用then方法,而每次调用then返回的Promise的状态取决于那一次调用then时传入参数的返回值,所以then不能返回this,因为then每次返回的Promise的结果都有可能不同。

image.png


以上代码片段来源于网络~那么,你学到了吗?