手拉手,一步一步带你实现promise原理

手拉手,一步一步带你实现promise原理

前言

  • 就在半个月前,一个后端的同事问我,为啥网上promise的实现原理里面有setTimeout呢?
  • 我说我没了解过,但过后还是抱着好奇去了解promise的实现原理,然后。。。就有了下面这篇文章
  • 等到我搞懂promise的实现原理之后,准备回答他有关setTimeout这个问题的时候,他说:哦!我上次说错了,我说的是axios的实现原理,啊这。。。。。。 废话不多说,直接进入正题

文件准备

  • 建立一个文件夹 里面包含三个文件 promise.js index.js test.js

  • promise.js 用于手写我们的Promise

  • index.js 用于使用标准Promise验证对比我们写的Promise

  • test.js 用于测试我们写的Promise 同样代码需要分别放在test.js index.js 执行

  • 如下图

文件准备.png

  • 说明:运行index.js 或者 test.js 全部手动用 node index.js 或者 node test.js 闲麻烦可以用nodemon,自行百度

Promises/A+规范

  • Promise 对象是异步编程的一种解决方案,最早由社区提出。Promises/A+ 规范是 JavaScript Promise 的标准,规定了一个 Promise 所必须具有的特性
  • Promises/A+规范文章 promisesaplus.com/ 能不能打开全靠手气
  • 我根据上面Promises/A+规范文章,翻译并总结成 规范1 规范2 规范3 (具体见下文)

正片开始

Promise用法

  • 日常开发,Promise主要是用来处理异步编程

  • 如何使用,看下面代码,在index.js中运行(node index.js)

    const promise1 = new Promise((resolve,reject)=>{
        console.log(1)
        resolve('解决')
        // reject('拒绝')
    });
    promise1.then(value1=>{console.log('value1',value1)},reason1=>{console.log('reson1',reason1)})
    // 输出 1  value1 解决
    // reson1 拒绝
    复制代码

分析

  • 先看看 规范1

    规范11 promise 有三种状态,分别是 待定(pending) 已完成(fulfilled) 已拒绝(rejected)
    	1.1 待定(pending): 可能转换为 已完成(fulfilled) 或者 已拒绝(rejected)
    	1.2 已完成(fulfilled):必须由待定(pending)转换过来,不可变化,必须有一个不能改变的值来表示,我们称为终值value
    	1.3 已拒绝(rejected):必须由待定(pending)转换过来,不可变化,必须有一个不能改变的值表示,我们称为拒因reason
    复制代码
  • 再看new Promise,说明 Promise是个构造函数 ,new Promise 传递的是一个函数(取名为executor)

  • 并且在Promise类内部,executor是立即执行的

代码思路
  • 我们需要定义一个构造函数Promise

  • 构造函数里面有一个表示当前状态的值state

  • 构造函数里面有一个表示Promise已完成(fulfilled)的终值value

  • 构造函数里面有一个表示Promise已拒绝(rejected)的拒因reason

  • 并且立即执行executor函数,于是在promise.js文件中写入:

    // promise.js
    class Promise {
        constructor(executor) {
            this.state = 'pending';
            this.value = null;
            this.reason = null;
            executor()
        }
    }
    module.exports = Promise;
    复制代码
  • 同样在test.js文件中写入

    // test.js
    const Promise = require('./promise')
    const promise = new Promise((resolve,reject)=>{
        console.log(1)
    })
    // 输出 1 
    复制代码
  • 为了防止不必要的失误,我提醒一下:**const Promise = require('./promise') **这个代码永远存在在test.js文件中,且不被注释

  • 接下来,我们接着思考:

思考

  • 先看下面代码(可以在index.js运行):

    const promise = new Promise((resolve,reject)=>{
        console.log(1)
        resolve(2)
    })
    promise.then(value => {
        console.log('value',value)
    })
    // 输出 1 2
    复制代码
分析
  • 在promise.js文件中,executor() 没有传入参数

  • 由上面代码中resolve(2) 可知:resolve和reject是函数,并且由构造函数提供

  • 我们知道(强行你们知道):

    • resolve 方法的作用是:将待定状态(pending)转化为已完成状态(fulfilled) ,并且把resolve(value)中的value值,赋值给构造函数Promise中的value属性,并且转换之前的状态必须是pending状态。

    • reject方法的作用是:将待定状态(pending)转化为已拒绝状态(rejected) ,并且把reject(reason)中的reason值,赋值给构造函数Promise中的reason属性,并且转换之前的状态必须是pending状态

  • 分析之后我们可以更新promise.js文件:

更新promise.js代码如下
class Promise {
    constructor(executor) {
        this.state = 'pending';
        this.value = null;
        this.reason = null;
        // 两方法传递给executor并且立即执行
        executor(this.resolve,this.reject)
    }
    // 往 Promise类中 添加 resolve方法
    resolve(value) {
        if(this.state === 'pending') {
            this.state = 'fulfilled';
            this.value = value;
        }
    }
    // 往 Promise类中 添加 reject方法
    reject(reason) {
        if(this.state === 'pending') {
            this.state = 'rejected';
            this.reason = reason;
        }
    }
}
module.exports = Promise;
复制代码
注意
  • 因为函数resolve和reject是在构造函数Promise外边执行的,所以函数resolve和reject的this指向不是指向Promise的实例(指向undefined),我们要用bind绑定this
  • 还有当前Promise构造函数中有三个常量 'pending' 'fulfilled' 'rejected'。我们可以在Promise类上定义三个变量来存储,防止我们写代码拼写错误,减少不必要的bug。
  • 稍微优化一下promise.js代码

更新promise.js代码如下

class Promise {
    constructor(executor) {
        // 初始化 状态 终值 拒因
        this.initValue()
        // 改变 resolve reject函数的this 指向
        this.initBind()
        // 立即执行 executor
        executor(this.resolve,this.reject)
    }
    initValue() {
        this.state = Promise.PENDING;
        this.value = null;
        this.reason = null;
    }
    initBind() {
        this.resolve = this.resolve.bind(this)
        this.reject = this.reject.bind(this)
    }
    resolve(value) {
        if(this.state === Promise.PENDING) {
            this.state = Promise.FULFILLED;
            this.value = value;
        }
    }
    reject(reason) {
        if(this.state === Promise.PENDING) {
            this.state = Promise.REJECTED;
            this.reason = reason;
        }
    }
}
// 定义三个常量
Promise.PENDING = 'pending';
Promise.FULFILLED = 'fulfilled';
Promise.REJECTED = 'rejected';
module.exports = Promise;
复制代码

这里有一个注意点

  • 当executor 不是一个函数的时候,比如我们可以在index.js 运行如下代码:
new Promise(1)
// 结果  TypeError: Promise resolver 1 is not a function
复制代码
  • 因此我们应该对executor加多一个判断

更新promise.js函数----对executor判断

class Promise {
    constructor(executor) {
        // 对executor类型判断 不是函数 直接抛出错误
       if(typeof executor !== 'function') {
           throw new TypeError(`Promise resolver ${executor} is not a function`)
       }
        this.initValue()
        this.initBind()
        executor(this.resolve,this.reject)
    }
    initValue() {
        this.state = Promise.PENDING;
        this.value = null;
        this.reason = null;
    }
    initBind() {
        this.resolve = this.resolve.bind(this)
        this.reject = this.reject.bind(this)
    }
    resolve(value) {
        if(this.state === Promise.PENDING) {
            this.state = Promise.FULFILLED;
            this.value = value;
        }
    }
    reject(reason) {
        if(this.state === Promise.PENDING) {
            this.state = Promise.REJECTED;
            this.reason = reason;
        }
    }
}
Promise.PENDING = 'pending';
Promise.FULFILLED = 'fulfilled';
Promise.REJECTED = 'rejected';
module.exports = Promise;
复制代码
  • 到此为止,Promise的 规范1 实现了,是不是很简单啊,promise?就这?好戏在后头(手动狗头)

then方法

  • 我们接下来讲规范2,让我娓娓道来。
规范22 then方法
		用法:promise.then(onFulfilled, onRejected)
	2.1 这两个onFulfilled和onRejected都是可选的参数
		2.1.1 如果onFulfilled不是函数,则必须忽略它 => 其实不是忽略,是将他重新赋值一个函数 下文会讲到
    	2.1.2 如果onRejected不是函数,则必须忽略它 => 其实不是忽略,是将他重新赋值一个函数 下文会讲到
	2.2 如果onFulfilled是一个函数
		2.2.1 必须在promise完成(由pending到fulfilled,即调用resolve(value))后才调用它,并将promise的值(终值				  value)作为它的第一个参数
    	2.2.2 在promise完成之前不能调用它
	2.3 如果onRejected是一个函数,
		2.3.1 必须在promise被拒绝(由pending到rejected,即调用reject(reason)后才调用它,并将promise的(拒因reason)作               为它的第一个参数
    	2.3.2 在promise被拒绝之前不能调用它
	2.4 then 必须返回一个promise实例,这样才可以实现链式调用,后文会讲

我们看看下面例子:
	eg: promise2 = promise1.then(onFulfilled, onRejected);

		2.4.1  如果onFulfilled或onRejected的返回值为x,则运行函数resolvePromise(promise2, x)
			   // 说明: 函数resolvePromise是我们自己定义的,后文会讲到
		2.4.2  如果onFulfilled或onRejected抛出异常e,则promise2必须以拒绝e为拒因
    	2.4.3  如果onFulfilled不是函数并且promise1被满足,则必须用promise1被满足的终值来满足promise2,并把这个终值传递			   给promise2.then 的成功回调函数的第一个参数
    	2.4.4  如果onRejected不是函数并被promise1拒绝,则必须用promise1被拒绝的拒因来拒绝promise2,并把这个拒因传递给				   promise2.then 的失败回调函数的第一个参数
复制代码

啃完规范之后,很无聊,接下来让我们一个一个分析解决

分析:
  • 由上面的规范,我们知道,then接受两个可选的参数理想状态肯定两个都是函数啦,我们先实现理想状态的情况
  • 当resolve(value)时,会执行then的onFulfilled函数,并且把value作为终值,传给onFulfilled函数,reject(reason)同理
  • 这里我们先解决规范2中的 2.2 2.3 => onFulfilled, onRejected都是函数的理想状态

更新promise.js函数 ----添加then方法

class Promise {
    constructor(executor) {
       if(typeof executor !== 'function') {
           throw new TypeError(`Promise resolver ${executor} is not a function`)
       }
        this.initValue()
        this.initBind()
        executor(this.resolve,this.reject)
    }
    initValue() {
        this.state = Promise.PENDING;
        this.value = null;
        this.reason = null;
    }
    initBind() {
        this.resolve = this.resolve.bind(this)
        this.reject = this.reject.bind(this)
    }
    resolve(value) {
        if(this.state === Promise.PENDING) {
            this.state = Promise.FULFILLED;
            this.value = value;
        }
    }
    reject(reason) {
        if(this.state === Promise.PENDING) {
            this.state = Promise.REJECTED;
            this.reason = reason;
        }
    }
    // 添加then 方法 
    then(onFulfilled, onRejected) {
        if(this.state === Promise.FULFILLED) {
            onFulfilled(this.value)
        }
        if(this.state === Promise.REJECTED) {
            onRejected(this.reason)
        }
    }
}
Promise.PENDING = 'pending';
Promise.FULFILLED = 'fulfilled';
Promise.REJECTED = 'rejected';
module.exports = Promise;
复制代码
  • 接下来来验证我们的成果,在index.js 和 test.js 文件中分别运行下面代码
 		let onFulfulled = value1 => {
            console.log('value1', value1)
        }
        let onRejected = reason1 => {
            console.log('reason1', reason1)
        }
        let promise1 = new Promise((resolve, reject) => {
            console.log('成功')
            resolve(1)
        });
        promise1.then(onFulfulled, onRejected)
        // 在index.js 和 test.js 的结果都是:
        // 成功
        // value1 1
复制代码
  • 看着结果,好像成功了呢,老厉害了,非也,我们再看看下面代码,在index.js和test.js中分别运行它

示例1

let onFulfulled = value1 => {
    console.log('value1', value1)
}
let onRejected = reason1 => {
    console.log('reason1', reason1)
}
console.log(1)
let promise1 = new Promise((resolve, reject) => {
    console.log(2)
    resolve(3)
});
promise1.then(onFulfulled, onRejected)
console.log(4)
// 在index.js文件中结果如下
// 1   2       4    value1 3
// 在test.js中结果如下
// 1   2   value1 3   4
复制代码
分析
  • 我们知道,在标准的Promise中,then是一个异步微任务,而在我们的promise.js中,then是个同步函数,当resolve(3)的时候,promise1的状态由待定变成已解决,即state="fulfulled",接着执行then方法,所以会先打印出3,才打印出 4。
问题1:
  • promise.js中的then是个同步函数,会先执行onFulfulled,然后再执行console.log(4)。
解决方式
  • setTimeout使onFulfulled和onRejected变成异步任务

更新promise.js----------给onFulfulled, onRejected分别加 setTimeout延迟执行

class Promise {
    constructor(executor) {
        if (typeof executor !== 'function') {
            throw new TypeError(`Promise resolver ${executor} is not a function`)
        }
        this.initValue()
        this.initBind()
        executor(this.resolve, this.reject)
    }
    initValue() {
        this.state = Promise.PENDING;
        this.value = null;
        this.reason = null;
    }
    initBind() {
        this.resolve = this.resolve.bind(this)
        this.reject = this.reject.bind(this)
    }
    resolve(value) {
        if (this.state === Promise.PENDING) {
            this.state = Promise.FULFILLED;
            this.value = value;
        }
    }
    reject(reason) {
        if (this.state === Promise.PENDING) {
            this.state = Promise.REJECTED;
            this.reason = reason;
        }
    }
    then(onFulfilled, onRejected) {
        if (this.state === Promise.FULFILLED) {
            // 添加 setTimeout 延迟 onFulfilled执行
            setTimeout(() => {
                onFulfilled(this.value)
            })

        }
        if (this.state === Promise.REJECTED) {
            // 添加 setTimeout 延迟 onRejected执行
            setTimeout(() => {
                onRejected(this.reason)
            })
        }
    }
}
Promise.PENDING = 'pending';
Promise.FULFILLED = 'fulfilled';
Promise.REJECTED = 'rejected';
module.exports = Promise;
复制代码

示例2

  • 接下来我们来看另外一种情况:这也是平常我们用promise的常见的情况之一,当我们用ajax,或者**setTimeout **这种异步任务,等异步任务执行完,再执行resolve或reject的时候,会出现什么情况?

  • 看看下面代码,分别在index.js 和 test.js 文件中运行:

console.log(1)
new Promise((resolve, reject) => {
    console.log(2)
    // 重点注意 setTimeout
    setTimeout(()=>{
        resolve(3)
    })
}).then(value => {
    console.log('value',value)
},reason => {
    console.log('reason',reason)
})
console.log(4)

// 在index.js中结果为: 1  2  4   value 3
// 在test.js中结果为: 1 2 4  => 也就是说 then方法执行了没效果
复制代码
分析
  • 看示例2,当代码执行到 console.log(2) 之后,遇到 setTimeout 会将resolve(3)放到异步任务队列中,此时resolve(3)并不会立即执行,Promise的状态依然还是待定状态(pending),这个时候执行了then方法,这样并不会执行onFulfulled或onRejected函数。
问题2
  • 用setTimeout(()=>{resolve(3)}) then方法执行没意义。
解决
  • 结合示例2,我们可以在promise.js中定义两个数组onFulfilledCallbacks=[],onRejectedCallbacks=[]
  • 当promise处于等待态就执行then方法,那就把onFulfulled和onRejected函数分别放入这两个数组中
  • 等到一定时间之后**(同步任务执行完),再执行resolve(3),再将onFulfilledCallbacks数组里的函数依次执行**。reject 和 onRejectedCallbacks也同理。
  • 这种方式有点像发布订阅模式,你品,你细品,修改代码如下:
class Promise {
    constructor(executor) {
        if (typeof executor !== 'function') {
            throw new TypeError(`Promise resolver ${executor} is not a function`)
        }
        this.initValue()
        this.initBind()
        executor(this.resolve, this.reject)
    }
    initValue() {
        this.state = Promise.PENDING;
        this.value = null;
        this.reason = null;
        // 添加 onFulfilledCallbacks onRejectedCallbacks
        this.onFulfilledCallbacks = [];
        this.onRejectedCallbacks = [];
    }
    initBind() {
        this.resolve = this.resolve.bind(this)
        this.reject = this.reject.bind(this)
    }
    resolve(value) {
        if (this.state === Promise.PENDING) {
            this.state = Promise.FULFILLED;
            this.value = value;
            // 添加  依次执行
            this.onFulfilledCallbacks.forEach(fn => fn(this.value))
        }
    }
    reject(reason) {
        if (this.state === Promise.PENDING) {
            this.state = Promise.REJECTED;
            this.reason = reason;
            // 添加  依次执行
            this.onRejectedCallbacks.forEach(fn => fn(this.reason))
        }
    }
    then(onFulfilled, onRejected) {
        if (this.state === Promise.FULFILLED) {
            setTimeout(() => {
                onFulfilled(this.value)
            })

        }
        if (this.state === Promise.REJECTED) {
            setTimeout(() => {
                onRejected(this.reason)
            })
        }
        // 还是等待态的时候就执行then方法处理
        if (this.state === Promise.PENDING) {
            this.onFulfilledCallbacks.push((value) => {
                setTimeout(() => {
                    onFulfilled(value)
                })
            })
            this.onRejectedCallbacks.push((reason) => {
                setTimeout(() => {
                    onRejected(reason)
                })
            })
        }
    }
}
Promise.PENDING = 'pending';
Promise.FULFILLED = 'fulfilled';
Promise.REJECTED = 'rejected';
module.exports = Promise;
复制代码

示例3

  • 只有你想不到,没有标准Promise做不到的,假设我们在new Promise中传入的函数executor中,抛出错误

    new Promise((resolve, reject) => {
        throw('哈哈')
        resolve(1)
    }).then(value => {
        console.log('value',value)
    },reason => {
        console.log('reason',reason)
    })
    // index.js => reason 哈哈
    // test.js => Uncaught 哈哈 抛出错误
    复制代码
分析
  • 在我们的promise.js中,执行 executor函数的时候,如果遇到错误,就会直接抛出没有经过Promise类处理
问题3
  • 执行 executor函数,如果遇到程序错误,执行结果不一样
解决
  • 用try catch组合捕获executor函数异常,然后拒绝(reject)出去即可

更新promise.js文件 ----添加捕获executor函数异常

class Promise {
    constructor(executor) {
        if (typeof executor !== 'function') {
            throw new TypeError(`Promise resolver ${executor} is not a function`)
        }
        this.initValue()
        this.initBind()
        //  此处添加 try catch
        try {
            executor(this.resolve, this.reject)
        } catch (err) {
            this.reject(err)
        }

    }
    initValue() {
        this.state = Promise.PENDING;
        this.value = null;
        this.reason = null;
        this.onFulfilledCallbacks = [];
        this.onRejectedCallbacks = [];
    }
    initBind() {
        this.resolve = this.resolve.bind(this)
        this.reject = this.reject.bind(this)
    }
    resolve(value) {
        if (this.state === Promise.PENDING) {
            this.state = Promise.FULFILLED;
            this.value = value;
            this.onFulfilledCallbacks.forEach(fn => fn(this.value))
        }
    }
    reject(reason) {
        if (this.state === Promise.PENDING) {
            this.state = Promise.REJECTED;
            this.reason = reason;
            this.onRejectedCallbacks.forEach(fn => fn(this.reason))
        }
    }
    then(onFulfilled, onRejected) {
        if (this.state === Promise.FULFILLED) {
            setTimeout(() => {
                onFulfilled(this.value)
            })

        }
        if (this.state === Promise.REJECTED) {
            setTimeout(() => {
                onRejected(this.reason)
            })
        }
        if (this.state === Promise.PENDING) {
            this.onFulfilledCallbacks.push((value) => {
                setTimeout(() => {
                    onFulfilled(value)
                })
            })
            this.onRejectedCallbacks.push((reason) => {
                setTimeout(() => {
                    onRejected(reason)
                })
            })
        }
    }
}
Promise.PENDING = 'pending';
Promise.FULFILLED = 'fulfilled';
Promise.REJECTED = 'rejected';
module.exports = Promise;
复制代码
  • 再运行下代码示例3代码 问题3解决

链式调用

我们用promise的时候,可以这么用:promise.then().then() ....

再看看上面提到的规范,我们还没解决的有

2 then方法

		用法:promise.then(onFulfilled, onRejected)

	2.1 这两个onFulfilled和onRejected是可选的参数
		2.1.1 如果onFulfilled不是函数,则必须忽略它 => 其实不是忽略,是将他重新赋值一个函数 下文会讲到
    	2.1.2 如果onRejected不是函数,则必须忽略它 => 其实不是忽略,是将他重新赋值一个函数 下文会讲到
	// 2.2 2.3 上文已解决
	2.4 then 必须返回一个promise实例,这样才可以实现链式调用,后文会讲
我们看看下面例子:
	eg: promise2 = promise1.then(onFulfilled, onRejected);

	接着,我们将定义的函数resolvePromise 后文会讲到
		2.4.1  如果onFulfilled或onRejected的返回值为x,则运行函数resolvePromise(promise2, x)
		2.4.2  如果onFulfilled或onRejected抛出异常e,则promise2必须以拒绝e为拒因
    	2.4.3  如果onFulfilled不是函数并且promise1被满足,则必须用promise1被满足的终值来满足promise2,并把这个终值传递			   给promise2.then 的成功回调函数的第一个参数
    	2.4.4  如果onRejected不是函数并被promise1拒绝,则必须用promise1被拒绝的拒因来拒绝promise2,并把这个拒因传递给				   promise2.then 的失败回调函数的第一个参数
复制代码
  • 为了更好的理解,我们先解决规范2.4这个大魔头。
  • promise2 = promise1.then(onFulfilled, onRejected)
分析
  • 规范 2.4.1:如果onFulfilled或onRejected返回x,则运行函数resolvePromise(promise2, x)

    • 先看下面例子:

      let promise1 = new Promise((resolve, reject) => {
          resolve(1)
      })
      promise1.then(value => {
          // 重点注意 x
          return x;
          console.log('value',value)
      },reason => {
          console.log('reason',reason)
      })
      复制代码
    • 注意,return x 。这个x 可以取所有符合javascript数据类型的值

    • 万事开头难,不管怎么样,先定义resolvePromise函数

更新 promise.js === 定义resolvePromise函数,将onFulfilled或onRejected返回值赋值给变量x

class Promise {
    constructor(executor) {
        if (typeof executor !== 'function') {
            throw new TypeError(`Promise resolver ${executor} is not a function`)
        }
        this.initValue()
        this.initBind()
        try {
            executor(this.resolve, this.reject)
        } catch (err) {
            this.reject(err)
        }

    }
    initValue() {
        this.state = Promise.PENDING;
        this.value = null;
        this.reason = null;
        this.onFulfilledCallbacks = [];
        this.onRejectedCallbacks = [];
    }
    initBind() {
        this.resolve = this.resolve.bind(this)
        this.reject = this.reject.bind(this)
    }
    resolve(value) {
        if (this.state === Promise.PENDING) {
            this.state = Promise.FULFILLED;
            this.value = value;
            this.onFulfilledCallbacks.forEach(fn => fn(this.value))
        }
    }
    reject(reason) {
        if (this.state === Promise.PENDING) {
            this.state = Promise.REJECTED;
            this.reason = reason;
            this.onRejectedCallbacks.forEach(fn => fn(this.reason))
        }
    }
    then(onFulfilled, onRejected) {
        if (this.state === Promise.FULFILLED) {
            setTimeout(() => {
                // 返回值给x
                const x = onFulfilled(this.value)
            })

        }
        if (this.state === Promise.REJECTED) {
            setTimeout(() => {
                // 返回值给x
                const x = onRejected(this.reason)
            })
        }
        if (this.state === Promise.PENDING) {
            this.onFulfilledCallbacks.push((value) => {
                setTimeout(() => {
                    // 返回值给x
                    const x = onFulfilled(value)
                })
            })
            this.onRejectedCallbacks.push((reason) => {
                setTimeout(() => {
                    // 返回值给x
                    const x = onRejected(reason)
                })
            })
        }
    }
}
Promise.PENDING = 'pending';
Promise.FULFILLED = 'fulfilled';
Promise.REJECTED = 'rejected';
 // 定义resolvePromise函数
Promise.resolvePromise = function (promise2, x) {

}
module.exports = Promise;
复制代码

分析

  • 规范2.4: then必须返回一个promise实例

    • then方法里面返回一个promise实例
  • promise2 = promise1.then(onFulfilled, onRejected);

  • 规范2.4.2: 如果onFulfilled或onRejected抛出异常e,则promise2必须以拒绝e为拒因

  • 分别用try catch捕获onFulfilled和onRejected异常,然后拒绝(reject)给promise2

到这里,先更新 一下 promise.js === then方法返回一个promise实例,try,catch捕获异常,拒绝出去

class Promise {
    constructor(executor) {
        if (typeof executor !== 'function') {
            throw new TypeError(`Promise resolver ${executor} is not a function`)
        }
        this.initValue()
        this.initBind()
        try {
            executor(this.resolve, this.reject)
        } catch (err) {
            this.reject(err)
        }

    }
    initValue() {
        this.state = Promise.PENDING;
        this.value = null;
        this.reason = null;
        this.onFulfilledCallbacks = [];
        this.onRejectedCallbacks = [];
    }
    initBind() {
        this.resolve = this.resolve.bind(this)
        this.reject = this.reject.bind(this)
    }
    resolve(value) {
        if (this.state === Promise.PENDING) {
            this.state = Promise.FULFILLED;
            this.value = value;
            this.onFulfilledCallbacks.forEach(fn => fn(this.value))
        }
    }
    reject(reason) {
        if (this.state === Promise.PENDING) {
            this.state = Promise.REJECTED;
            this.reason = reason;
            this.onRejectedCallbacks.forEach(fn => fn(this.reason))
        }
    }
    then(onFulfilled, onRejected) {
        // 定义新的promise实例 promise2  并且 做为then方法的返回值
        let promise2 = new Promise((resolve2, reject2) => {
            if (this.state === Promise.FULFILLED) {
                setTimeout(() => {
                    // 捕获异常
                    try {
                        const x = onFulfilled(this.value)
                    } catch (err) {
                        reject2(err)
                    }
                })

            }
            if (this.state === Promise.REJECTED) {
                setTimeout(() => {
                    // 捕获异常
                    try {
                        const x = onRejected(this.reason)
                    } catch (err) {
                        reject2(err)
                    }
                })
            }
            if (this.state === Promise.PENDING) {
                this.onFulfilledCallbacks.push((value) => {
                    setTimeout(() => {
                        // 捕获异常
                        try {
                            const x = onFulfilled(value)
                        } catch (err) {
                            reject2(err)
                        }

                    })
                })
                this.onRejectedCallbacks.push((reason) => {
                    setTimeout(() => {
                        // 捕获错误
                        try {
                            const x = onRejected(reason)
                        } catch (err) {
                            reject2(err)
                        }
                    })
                })
            }
        })
        return promise2
    }
}
Promise.PENDING = 'pending';
Promise.FULFILLED = 'fulfilled';
Promise.REJECTED = 'rejected';
Promise.resolvePromise = function (promise2, x) {

}
module.exports = Promise;
复制代码

不要停下来,咱们继续

分析
  • promise2 = promise1.then(onFulfilled, onRejected)

  • 规范 2.4.3 如果onFulfilled不是函数并且promise1被满足,则promise1必须用与 相同的值来满足promise2

    • 解决: 这个要判断传进来的onFulfilled是不是函数,如果不是, 将解决promise1的value值,解决(resolve)promise2
  • 规范 2.4.4 如果onRejected不是函数并被promise1拒绝,则promise1必须以与 相同的拒因拒绝promise2

    • 解决: 这个要判断传进来的onRejected是不是函数,如果不是,将拒绝promise1的reason值,解决(resolve)promise2(注意,这里不是拒绝reject)
    代码思路
    • 我们可以先判断then传进来的两个方法onFulfulled, onRejected 是否为函数,如果不是函数 就分别给这两个函数赋新的函数

    • 新函数分别是 onFulfulled = (value) => value onRejected = (reason) => { throw( reason) }

    • 将 onFulfulled或者onRejected处理的值(执行onFulfulled或者onRejected函数的返回值x),解决(reolve)promise2

  • 其实这里也解决了下面的规范

      2.1 这两个onFulfilled和onRejected可选的参数
    	2.1.1 如果onFulfilled不是函数,则必须忽略它 => 其实不是忽略,是将他重新赋值一个函数 下文会讲到
          2.1.2 如果onRejected不是函数,则必须忽略它 => 其实不是忽略,是将他重新赋值一个函数 下文会讲到
    复制代码

更新promise.js 代码 === 判断then方法传入的参数是不是函数,并加以处理,把promise1的拒绝和解决,全部解决给promise2

class Promise {
    constructor(executor) {
        if (typeof executor !== 'function') {
            throw new TypeError(`Promise resolver ${executor} is not a function`)
        }
        this.initValue()
        this.initBind()
        try {
            executor(this.resolve, this.reject)
        } catch (err) {
            this.reject(err)
        }

    }
    initValue() {
        this.state = Promise.PENDING;
        this.value = null;
        this.reason = null;
        this.onFulfilledCallbacks = [];
        this.onRejectedCallbacks = [];
    }
    initBind() {
        this.resolve = this.resolve.bind(this)
        this.reject = this.reject.bind(this)
    }
    resolve(value) {
        if (this.state === Promise.PENDING) {
            this.state = Promise.FULFILLED;
            this.value = value;
            this.onFulfilledCallbacks.forEach(fn => fn(this.value))
        }
    }
    reject(reason) {
        if (this.state === Promise.PENDING) {
            this.state = Promise.REJECTED;
            this.reason = reason;
            this.onRejectedCallbacks.forEach(fn => fn(this.reason))
        }
    }
    then(onFulfilled, onRejected) {
        // 判断是否为函数
        if (typeof onFulfilled !== 'function') {
            onFulfilled = (value) => value;
        }
        // 判断是否为函数
        if (typeof onRejected !== 'function') {
            onRejected = (reason) => { throw reason };
        }
        let promise2 = new Promise((resolve2, reject2) => {
            if (this.state === Promise.FULFILLED) {
                setTimeout(() => {
                    try {
                        const x = onFulfilled(this.value)
                        // 解决promise2
                        resolve2(x)
                    } catch (err) {
                        reject2(err)
                    }
                })

            }
            if (this.state === Promise.REJECTED) {
                setTimeout(() => {
                    try {
                        const x = onRejected(this.reason)
                        // 解决promise2
                        resolve2(x)
                    } catch (err) {
                        reject2(err)
                    }
                })
            }
            if (this.state === Promise.PENDING) {
                this.onFulfilledCallbacks.push((value) => {
                    setTimeout(() => {
                        try {
                            const x = onFulfilled(value)
                           // 解决promise2
                            resolve2(x)
                        } catch (err) {
                            reject2(err)
                        }

                    })
                })
                this.onRejectedCallbacks.push((reason) => {
                    setTimeout(() => {
                        try {
                            const x = onRejected(reason)
                            // 解决promise2
                            resolve2(x)
                        } catch (err) {
                            reject2(err)
                        }
                    })
                })
            }
        })
        return promise2
    }
}
Promise.PENDING = 'pending';
Promise.FULFILLED = 'fulfilled';
Promise.REJECTED = 'rejected';
Promise.resolvePromise = function (promise2, x) {

}
module.exports = Promise;
复制代码
  • 为了加深理解

  • promise2 = promise1.then(onFulfilled, onRejected)

    我们分别在index.js 和 test.js 运行下面的代码

    // 这种情况是promise1 已被解决 但promise1.then 的 onFulfulled不是函数,是个 1
    let promise1 = new Promise((resolve, reject) => {
        resolve('解决但onFulfulled不是函数')
    })
    // 注意下面的1
    let promise2 = promise1.then(1,reason1 => {
        console.log('reason1', reason1)
    })
    promise2.then(value1 => {
        console.log('value1',value1)
    }, reason1 => {
        console.log('reason1', reason1)
    })
    // index.js 输出 value1 解决但onFulfulled不是函数 
    // test.js 输出 value1 解决但onFulfulled不是函数
    复制代码
    • 结果符合我们的预期

    接着继续在index,js 和 test.js文件中运行

    // 这种情况是promise1 已被拒绝 但promise1.then 的 onRejected不是函数,没有传参
    let promise1 = new Promise((resolve, reject) => {
        reject('拒绝但onRejected不是函数')
    })
     // 注意这里then方法没有传拒绝回调函数
    let promise2 = promise1.then(value =>{
        console.log('value',value)
    })
    promise2.then(value1 => {
        console.log('value1',value1)
    }, reason1 => {
        console.log('reason1', reason1)
    })
    // index.js 输出 reason1 拒绝但onRejected不是函数
    // test.js 输出 reason1 拒绝但onRejected不是函数
    复制代码
    • 结果也符合我们的预期
  • 这看到这里,可能有些人会想,为啥promise1的then中onRejected不是函数,且promise1被拒绝(rejected),但仍然**要resolve(x)给promise2?**如下面代码所示:

 if (this.state === Promise.REJECTED) {
                setTimeout(() => {
                    try {
                        const x = onRejected(this.reason)
                        // 其实下面不会执行
                        resolve2(x)
                    } catch (err) {
                        reject2(err)
                    }
                })
            }
复制代码
  • 其实根本不会执行resolve2(x),前面我们判断onRejected不是函数的时候,执行了 onRejected = (reason) => { throw reason };,也就是说错误被捕获了,这里实际上是执行 reject2(err)

完结 第二部分的规范也已经完全解决了

ok ,你可以给自己来杯热茶,预祝胜利了,你已经完成了百分之八九十了,再坚持一下,就快修炼成功了,还记得我们前面提到的resolvePromise函数吗?

神奇的resolvePromise函数

  • 前面我们知道,onFulfilled或onRejected返回值x,x可以是符合javascript所有类型的值,我们现在考虑一个问题:
  • 如果x是个promise实例,或者x是个函数,亦或者x是个对象,我们应该怎么处理?这就不得不提前面提到的resolvePromise函数
  • 咱们先看看规范怎么说的
  • 规范3
3 resolvePromise函数
	3.1 如果promise和x引用同一个对象,promise以一个TypeError类型e为理由拒绝
	3.2 如果x是个promise实例
		3.2.1 promise必须保持挂起状态,直到x完成或被拒绝。
		3.2.2 何时x完成,则promise用相同的值完成
		3.2.3 何时x被拒绝,promise以同样的理由拒绝
	3.3 x是一个对象或函数
		3.3.1 看看x有没有then属性 有的话 让then = x.then 如果then是个函数 执行then 并且把then函数的this指向x,then还		   有可能抛出错误,用try catch捕获 然后reject出去
		3.3.2 如果x没有then属性,那么当成普通的值resolve出去,完成解决
	3.4 如果x不是拥有then方法的对象或者promise实例,直接解决resolve出去
	3.5 提倡但是不建议递归调用resolvePromise,不能无限递归调用 应该有一个标志called,来标志是否解决或者拒绝过
复制代码
  • 我们先来看看一个例子,我们分别在index.js test.js文件中运行下面代码
let promise1 = new Promise((resolve, reject) => {
    resolve(1)
})
let promise2 = promise1.then(value => {
	 // 关键代码 在 promise1的成功回调函数中 return一个promise实例
    return new Promise((resolve, reject) => {
        resolve(2)
    })
}, reason => {
    console.log('reason', reason)
})
promise2.then(value1 => {
    console.log('value1', value1)
}, reason1 => {
    console.log('reason1', reason1)
})
// 在index.js中  输出  value1 2
// 在test.js文件中输出 value1 Promise {
//  state: 'fulfilled',
//  value: 2,
//  reason: null,
//  onFulfilledCallbacks: [],
//  onRejectedCallbacks: [],
//  resolve: [Function: bound resolve],
//  reject: [Function: bound reject]
// }
复制代码
  • 也就是说,这是当x是一个promise实例的情况,我们写的promise.js文件会原样输出promise实例,而标准的promise是把这个promise执行完(解决或拒绝)之后抛出去给它的下一个promise实例,往复循环。
  • 因此,这个 x不能直接resolve(x),要分情况讨论,这也是规范3提到的:x可以分为promise实例对象或者函数普通值等的原因,这个时候就要用到我们前面提到的resolvePromise函数了,先更新一波代码

更新promise.js代码=====让x交给resolvePromise函数处理

class Promise {
    constructor(executor) {
        if (typeof executor !== 'function') {
            throw new TypeError(`Promise resolver ${executor} is not a function`)
        }
        this.initValue()
        this.initBind()
        try {
            executor(this.resolve, this.reject)
        } catch (err) {
            this.reject(err)
        }

    }
    initValue() {
        this.state = Promise.PENDING;
        this.value = null;
        this.reason = null;
        this.onFulfilledCallbacks = [];
        this.onRejectedCallbacks = [];
    }
    initBind() {
        this.resolve = this.resolve.bind(this)
        this.reject = this.reject.bind(this)
    }
    resolve(value) {
        if (this.state === Promise.PENDING) {
            this.state = Promise.FULFILLED;
            this.value = value;
            this.onFulfilledCallbacks.forEach(fn => fn(this.value))
        }
    }
    reject(reason) {
        if (this.state === Promise.PENDING) {
            this.state = Promise.REJECTED;
            this.reason = reason;
            this.onRejectedCallbacks.forEach(fn => fn(this.reason))
        }
    }
    then(onFulfilled, onRejected) {
        if (typeof onFulfilled !== 'function') {
            onFulfilled = (value) => value;
        }
        if (typeof onRejected !== 'function') {
            onRejected = (reason) => { throw reason };
        }
        let promise2 = new Promise((resolve2, reject2) => {
            if (this.state === Promise.FULFILLED) {
                setTimeout(() => {
                    try {
                        // 让x交给resolvePromise函数处理
                        const x = onFulfilled(this.value)
                        Promise.resolvePromise(promise2,x,resolve2,reject2)
                        // resolve2(x)
                    } catch (err) {
                        reject2(err)
                    }
                })

            }
            if (this.state === Promise.REJECTED) {
                setTimeout(() => {
                    try {
                        // 让x交给resolvePromise函数处理
                        const x = onRejected(this.reason)
                        Promise.resolvePromise(promise2,x,resolve2,reject2)
                        // resolve2(x)
                    } catch (err) {
                        reject2(err)
                    }
                })
            }
            if (this.state === Promise.PENDING) {
                this.onFulfilledCallbacks.push((value) => {
                    setTimeout(() => {
                        try {
                            // 让x交给resolvePromise函数处理
                            const x = onFulfilled(value)
                            Promise.resolvePromise(promise2,x,resolve2,reject2)
                            // resolve2(x)
                        } catch (err) {
                            reject2(err)
                        }

                    })
                })
                this.onRejectedCallbacks.push((reason) => {
                    setTimeout(() => {
                        try {
                            // 让x交给resolvePromise函数处理
                            const x = onRejected(reason)
                            Promise.resolvePromise(promise2,x,resolve2,reject2)
                            // resolve2(x)
                        } catch (err) {
                            reject2(err)
                        }
                    })
                })
            }
        })
        return promise2
    }
}
Promise.PENDING = 'pending';
Promise.FULFILLED = 'fulfilled';
Promise.REJECTED = 'rejected';
Promise.resolvePromise = function (promise2,x,resolve2,reject2) {

}
module.exports = Promise;
复制代码

再结合规范3,我们一步一步分析处理

  • 我们可以先初始化条件判断的代码如下:

    Promise.resolvePromise = function (promise2, x,resolve2,reject2) {
    	// x是个和promise2相同
        if (promise2 === x) {
          
        }
        // x是个Promise实例
        if (x instanceof Promise) {
           
        }
        // x是个对象或者函数
        else if(x !== null && (typeof x === 'function' || typeof x === 'object') {
        
        }
        // x是个普通值
        else {
            
        }
    }
    复制代码
  • 规范3.1: 如果promise和x引用同一个对象,promise以一个TypeError类型e为理由拒绝

    • 可以再index.js文件中运行如下
    let promise1 = new Promise((resolve,reject) => {
        resolve(1)
    })
    let promise2 = promise1.then(value =>{
        return promise2
    })
    // 运行结果 TypeError: Chaining cycle detected for promise
    复制代码
    • promise2 永远等待promise2执行完才会执行,自己等自己,这不是陷入了死循环了吗? (下文解决)
  • 规范3.4 :如果x不是promise实例或者不是一个拥有then方法的对象,直接解决(resolve)

  • 结合 规范3.1 规范3.4 更新resolvePromise函数如下:

Promise.resolvePromise = function (promise2, x,resolve2,reject2) {
	// x是个和promise相同
    if (promise2 === x) {
       // 规范3.1处理
      reject2(new TypeError('Chaining cycle detected for promise'))
    }
    // x是个Promise实例
    if (x instanceof Promise) {
       
    }
    // x是个对象或者函数
    else if(x !== null && (typeof x === 'function' || typeof x === 'object') {
    
    }
    // x是个普通值 =》 不是promise实例或者不是一个拥有then方法的对象
    else {
    	// 看上面规范 3.4 如果x不是拥有then方法的对象或者promise实例,直接解决(resolve)出去
        resolve2(x)
    }
}
复制代码
  • 规范3.2: 如果x是个promise实例 3.2.1 promise必须保持挂起状态,直到x完成或被拒绝。 3.2.2 何时x完成,则promise用相同的值完成 3.2.3 何时x被拒绝,promise以同样的理由拒绝

    • 说白了就是等待这个promise实例解决或拒绝再处理出去
    Promise.resolvePromise = function (promise2, x,resolve2,reject2) {
    	// x是个和promise相同
        if (promise2 === x) {
          // 规范3.1
          reject2(new TypeError('Chaining cycle detected for promise'))
        }
        // x是个Promise实例
        if (x instanceof Promise) {
            x.then(value => {
                // 这里不是resolve(value) 下文有说明
                Promise.resolvePromise(promise2, value, resolve2, reject2)
            }, reason => {
                reject2(reason)
            })
        }
        // x是个对象或者函数
        else if(x !== null && (typeof x === 'function' || typeof x === 'object') {
        	
        }
        // x是个普通值
        else {
        	// 看上面规范 3.4 如果x不是拥有then方法的对象或者promise实例,直接解决resolve出去
            resolve2(x)
        }
    }
    复制代码
    • 说明:上面代码没有用resolve(value)而用Promise.resolvePromise(promise2, value, resolve2, reject2) 就是防止疯狂套娃情况,比如return 的promise实例之后,其then方法里面的成功回调函数又 return一个 promise实例 ,如此往复。大哥你可真行啊,这么能套娃,但是,不管你怎么套娃,不考虑异常报错的情况下,我们最终都会处理到x是个普通值,然后resolve(x)出去。
  • 规范3.3:x是一个对象或函数 3.3.1 看看x有没有then属性,有的话,让then = x.then,如果then是个函数,执行then 并且把then函数的this指向x,同时用try catch捕获then函数执行抛出错误,,然后拒绝(reject)出去。 3.3.2 如果x没有then属性,那么当成普通的值resolve出去,完成解决

按照规范更新代码

Promise.resolvePromise = function (promise2, x,resolve2,reject2) {
	// x是个和promise相同
    if (promise2 === x) {
      reject2(new TypeError('Chaining cycle detected for promise'))
    }
    // x是个Promise实例
    if (x instanceof Promise) {
        x.then(value => {
            Promise.resolvePromise(promise2, value, resolve2, reject2)
        }, reason => {
            reject2(reason)
        })
    }
    // x是个对象或者函数
    else if(x !== null && (typeof x === 'function' || typeof x === 'object')) {
        // 规范3.3 try catch 捕获then函数错误  
        // then成功回调函数返回值再交给resolvePromise(promise2, value, resolve2, reject2)
        try {
        	const then = x.then;
            if (typeof then === 'function') { 
                then.call(x, value => {
                    Promise.resolvePromise(promise2, value, resolve2, reject2)
                }, reason => {
                    reject2(reason)
                })
            } else {
                resolve2(x)
            }
        }catch(err) {
            reject2(err)
        }
    }
    // x是个普通值
    else {
    	// 看上面规范 3.4 如果x不是拥有then方法的对象或者promise实例,直接解决resolve出去
        resolve2(x)
    }
}
复制代码
  • 3.5 规范不建议resolvePromise无限递归调用 应该有一个标志called,调用一次之后不再调用了

更新代码如下====这也是resolvePromise最终代码了

Promise.resolvePromise = function (promise2, x, resolve2, reject2) {
    // x是个和promise相同
    if (promise2 === x) {
        reject2(new TypeError('Chaining cycle detected for promise'))
    }
    // called 标志是否处理过(成功或者拒绝)
    let called = false;
    // x是个Promise实例
    if (x instanceof Promise) {
        x.then(value => {
            Promise.resolvePromise(promise2, value, resolve2, reject2)
        }, reason => {
            reject2(reason)
        })
    }
    // x是个对象或者函数
    else if (x !== null && (typeof x === 'function' || typeof x === 'object')) {
        try {
        	const then = x.then;
            if (typeof then === 'function') {
                then.call(x, value => {
                    // 新增 called判断
                    if (called) return
                    called = true;
                    Promise.resolvePromise(promise2, value, resolve2, reject2)
                }, reason => {
                     // 新增 called判断
                    if (called) return
                    called = true;
                    reject2(reason)
                })
            } else {
                // 新增 called判断
                if (called) return
                called = true;
                resolve2(x)
            }
        } catch (err) {
            // 新增 called判断
        	if (called) return
            called = true;
            reject2(err)
        }
    }
    // x是个普通值
    else {
        // 看上面规范 3.4 如果x不是拥有then方法的对象或者promise实例,直接解决resolve出去
        resolve2(x)
    }
}
复制代码

更新promise.js代码 ==== 最终更新

class Promise {
    constructor(executor) {
        if (typeof executor !== 'function') {
            throw new TypeError(`Promise resolver ${executor} is not a function`)
        }
        this.initValue()
        this.initBind()
        try {
            executor(this.resolve, this.reject)
        } catch (err) {
            this.reject(err)
        }

    }
    initValue() {
        this.state = Promise.PENDING;
        this.value = null;
        this.reason = null;
        this.onFulfilledCallbacks = [];
        this.onRejectedCallbacks = [];
    }
    initBind() {
        this.resolve = this.resolve.bind(this)
        this.reject = this.reject.bind(this)
    }
    resolve(value) {
        if (this.state === Promise.PENDING) {
            this.state = Promise.FULFILLED;
            this.value = value;
            this.onFulfilledCallbacks.forEach(fn => fn(this.value))
        }
    }
    reject(reason) {
        if (this.state === Promise.PENDING) {
            this.state = Promise.REJECTED;
            this.reason = reason;
            this.onRejectedCallbacks.forEach(fn => fn(this.reason))
        }
    }
    then(onFulfilled, onRejected) {
        if (typeof onFulfilled !== 'function') {
            onFulfilled = (value) => value;
        }
        if (typeof onRejected !== 'function') {
            onRejected = (reason) => { throw reason };
        }
        let promise2 = new Promise((resolve2, reject2) => {
            if (this.state === Promise.FULFILLED) {
                setTimeout(() => {
                    try {
                        const x = onFulfilled(this.value)
                        Promise.resolvePromise(promise2, x, resolve2, reject2)
                    } catch (err) {
                        reject2(err)
                    }
                })

            }
            if (this.state === Promise.REJECTED) {
                setTimeout(() => {
                    try {
                        const x = onRejected(this.reason)
                        Promise.resolvePromise(promise2, x, resolve2, reject2)
                    } catch (err) {
                        reject2(err)
                    }
                })
            }
            if (this.state === Promise.PENDING) {
                this.onFulfilledCallbacks.push((value) => {
                    setTimeout(() => {
                        try {
                            const x = onFulfilled(value)
                            Promise.resolvePromise(promise2, x, resolve2, reject2)
                        } catch (err) {
                            reject2(err)
                        }

                    })
                })
                this.onRejectedCallbacks.push((reason) => {
                    setTimeout(() => {
                        try {
                            const x = onRejected(reason)
                            Promise.resolvePromise(promise2, x, resolve2, reject2)
                        } catch (err) {
                            reject2(err)
                        }
                    })
                })
            }
        })
        return promise2
    }
}
Promise.PENDING = 'pending';
Promise.FULFILLED = 'fulfilled';
Promise.REJECTED = 'rejected';
Promise.resolvePromise = function (promise2, x, resolve2, reject2) {
    // x是个和promise相同
    if (promise2 === x) {
        reject2(new TypeError('Chaining cycle detected for promise'))
    }
    // called 标志是否处理(成功或者解决值)
    let called = false;
    // x是个Promise实例
    if (x instanceof Promise) {
        x.then(value => {
            Promise.resolvePromise(promise2, value, resolve2, reject2)
        }, reason => {
            reject2(reason)
        })
    }
    // x是个对象或者函数
    else if (x !== null && (typeof x === 'function' || typeof x === 'object')) {
        try {
            const then = x.then;
            if (typeof then === 'function') {
                then.call(x, value => {
                    if (called) return
                    called = true;
                    Promise.resolvePromise(promise2, value, resolve2, reject2)
                }, reason => {
                    if (called) return
                    called = true;
                    reject2(reason)
                })
            } else {
                if (called) return
                called = true;
                resolve2(x)
            }
        } catch (err) {
            if (called) return
            called = true;
            reject2(err)
        }
    }
    // x是个普通值
    else {
        // 看上面规范 3.4 如果x不是拥有then方法的对象或者promise实例,直接解决resolve出去
        resolve2(x)
    }
}
module.exports = Promise;
复制代码

至此,大家伙们,Promise的实现原理终终终终终终终终于搞定了

测试成果

  • 我说搞定了就搞定了吗。我们还是让程序说话吧

    • 我们可以通过 promises-aplus-tests 来测试我们实现的Promise原理是否满足 Promise/A+ 规范。

    • 安装 npm install promises-aplus-tests

    • 在promise.js中加入代码:

      class Promise {
          ....这里是我们写的代码
      }
      ...
      ...
      module.exports = Promise;
      // 这一部分是我们加入的代码
      Promise.defer = Promise.deferred = function () {
          let dfd = {}
          dfd.promise = new Promise((resolve, reject) => {
              dfd.resolve = resolve
              dfd.reject = reject
          })
          return dfd
      }
      复制代码
    • 运行 npx promises-aplus-tests promise.js

测试结果

测试结果.png

这波真的大功告成了

参考文献

猜你喜欢

转载自juejin.im/post/7039903092208304158