想要实现一个Promise,首先要了解Promise的一些特性和用法以及PromiseA+规范,了解用法和规范后,按照规范一步一步实现一个Promise类
Promise的用法和特点
- promise有且仅有下列状态中的其中一种状态
- 等待态
pending - 成功态
resolved - 失败态
rejected
- 等待态
- 只有promise当前状态是
penging时,才能将当前状态改变为resolved或者是rejected,其他情况不存在状态改变 - Promise构造函数的第一个参数为
executor,执行new Promise的时候executor会立即执行
const p = new Promise((resolve, reject) => {
console.log('立即执行了')
})
console.log(111)
可以看到先打印了立即执行了,再打印111
- 当executor中抛出错误时,
promise状态就会转变为失败态 executor接收两个参数resolve和reject(resolve和reject都是函数),当当前promise状态为pending的时候,调用resolve将promise状态改变为resolved,或者调用reject,将promise状态改变为rejected- 每个promise实例都提供了一个
then方法,在then方法中接收两个参数onFulfilled, onRejected,分别是成功的回调函数和失败的回调函数,then方法是异步的,属于微任务
const p = new Promise((resolve, reject) => {
console.log(111)
resolve(222)
})
p.then(res => {
console.log(res, 'res')
}, err => {
console.log(err, 'err')
})
console.log(333)
结果如下:
promise的then可以链式调用多次,成功时会执行所有的成功回调,失败时会执行所有的失败回调
实现一个Promise
在由简单到复杂的使用中实现一步一步实现一个Promise
先实现一个满足下面代码运行的Promise类
const p1 = new Promise((resolve, reject) => {
resolve(2)
})
p1.then(res => {
console.log(res, 'success');
}, err => {
console.log(err, 'error');
})
// 输出 2 'success'
源码实现部分:
const PENDING = 'pending',
RESOLVED= 'resolved',
REJECTED = 'rejected'
class Promise {
constructor(executor) {
this.status = PENDING // 当前promise的状态
this.value = undefined // 成功态对应的value
this.reason = undefined // 失败态对应的reason
/*
* 只有当状态为pending的时候才能够转换状态
*/
const resolve = value => {
if(this.status === PENDING) {
this.status = RESOLVED
this.value = value
}
}
const reject = reason => {
if(this.status === PENDING) {
this.status = REJECTED
this.reason = reason
}
}
executor(resolve, reject)
}
/*
* onFulfilled: 一定是在promise是resolved状态后调用,并且接受一个参数 value
* onRejected: 一定在 promise是rejected状态后调用,并且接受一个参数 reason
*/
then(onFulfilled, onRejected) {
if(this.status === RESOLVED) {
onFulfilled(this.value)
}
if(this.status === REJECTED) {
onRejected(this.reason)
}
}
}
这样就可以实现上面的效果,也可以打印出2 success的效果
- 当执行
executor函数时,如果内部出错,就直接转换为rejected状态,所以可以在执行executor时加上try catch来捕获错误
try {
executor(resolve, reject)
}catch(e) {
reject(e)
}
- 目前
executor代码内的代码是同步的运行起来是没有任何问题的,但是如果里面是异步的呢,这样就有问题了,以现在实现的Promise为基础运行以下代码
const p1 = new Promise((resolve, reject) => {
setTimeout(() => {
resolve(2)
}, 1000)
})
p1.then(res => {
console.log(res, 'success');
}, err => {
console.log(err, 'error');
})
运行代码,发现什么也没发生,
原因:
执行new Promise(executor)立即执行executor,遇到了setTimeout,而setTimeout是异步的,会先将setTimeout的回调放到异步队列中,所以resolve并没有执行,当前promise的状态还是pending,而promise的then方法是微任务,所以先执行then,而这时候promise的状态还是pending,所以onFulfilled/onRejected都没有执行,而当一秒后执再行resolve,这时then方法已经执行过了,便不会再执行了。
解决办法:
在执行then方法时,如果当前的状态是pending,就把注册的onFulfilled和onRejected方法先保存起来,等到状态变为resolved时,再依次执行保存的方法
代码如下:
class Promise {
constructor(executor) {
this.status = PENDING // 当前promise的状态
this.value = undefined // 成功态对应的value
this.reason = undefined // 失败态对应的reason
this.onResolvedCallbacks = [] // 存储then函数的成功回调数组
this.onRejectedCallbacks = [] // 存储then函数的失败回调数组
/*
* 只有当状态为pending的时候才能够转换状态
*/
const resolve = value => {
if(this.status === PENDING) {
this.status = RESOLVED
this.value = value
/*
* 状态变为resolved之后,依次执行保存的成功回调
* */
this.onResolvedCallbacks.forEach(fn => fn())
}
}
const reject = reason => {
if(this.status === PENDING) {
this.status = REJECTED
this.reason = reason
/*
* 状态变为rejected之后,依次执行保存的失败回调
* */
this.onRejectedCallbacks.forEach(fn => fn())
}
}
try {
executor(resolve, reject)
}catch(e) {
reject(e)
}
}
/*
* onFulfilled: 一定是在promise是resolved状态后调用,并且接受一个参数 value
* onRejected: 一定在 promise是rejected状态后调用,并且接受一个参数 reason
* */
then(onFulfilled, onRejected) {
if(this.status === RESOLVED) {
onFulfilled(this.value)
}
if(this.status === REJECTED) {
onRejected(this.reason)
}
/*
* 状态为pending时,将成功和失败回调存起来
* */
if(this.status === PENDING) {
this.onResolvedCallbacks.push(() => {
onFulfilled(this.value)
})
this.onRejectedCallbacks.push(() => {
onRejected(this.reason)
})
}
}
}
现在再运行上面的例子就能够正常打印了
Promise链式调用
特点:
-
promise的then方法可以链式调用,then方法一定返回一个新的promise -
如果当前
then中的代码报错,则会传递给下一个then的失败回调
const p1 = new Promise((resolve, reject) => {
resolve(111)
})
p1
.then(res => {
console.log(a, 'p1 success')
}, err => {
console.log(err, 'p1 error')
})
.then(res => {
console.log(res, 'p1 then success')
}, err => {
console.log(err, 'p1 then error')
})
/*
* ReferenceError: a is not defined
* at <anonymous>:7:17 "p1 then error"
*/
-
如果当前
then中有返回值3.1 返回值是
promise,就把promise的结果传递给下一个then3.2 返回值是
普通值(除了promise以外的),就将这个值作为参数传递给下一个then的成功回调
- 如果当前
then中没有返回值,默认返回undefined
const p1 = new Promise((resolve, reject) => {
resolve(111)
})
p1
.then(res => {
console.log('p1 success')
return new Promise((resolve, reject) => { resolve('========')})
}, err => {
console.log(err, 'p1 error')
})
.then(res => {
console.log(res, 'p1 then success')
}, err => {
console.log(err, 'p1 then error')
})
/*
* p1 success
* ======== p1 then success
*/
const p1 = new Promise((resolve, reject) => {
resolve(111)
})
p1
.then(res => {
console.log('p1 success')
return '-----p1p1p1------'
}, err => {
console.log(err, 'p1 error')
})
.then(res => {
console.log(res, 'p1 then success')
}, err => {
console.log(err, 'p1 then error')
})
/*
* p1 success
* -----p1p1p1------ p1 then success
*/
- 当前
then没有任何处理逻辑,则无论成功还是失败都传递给下一个then的成功回调/失败回调
const p1 = new Promise((resolve, reject) => {
resolve(111)
})
p1
.then()
.then(res => {
console.log(res, 'p1 then success')
}, err => {
console.log(err, 'p1 then error')
})
/*
* 111 "p1 then success"
*/
const p1 = new Promise((resolve, reject) => {
reject(111)
})
p1
.then()
.then(res => {
console.log(res, 'p1 then success')
}, err => {
console.log(err, 'p1 then error')
})
/*
* 111 "p1 then error"
*/
- 当前
then如果走到了失败回调中,只要失败回调中不发生错误,下一个then还是会走成功回调
const p1 = new Promise((resolve, reject) => {
reject(222)
})
p1.then(res => {
console.log(res, '1success')
}, err => {
console.log(err, '1 fail')
}).then(res => {
console.log(res, '2 success')
}, err => {
console.log(err, '2 fail')
})
/*
* 222 "1 fail"
* undefined "2 success"
*/
根据以上使用,去实现源代码
promise.then一定是返回一个新的promise,因为通过上面的源代码可以知道,一个promise的状态和value/reason只能改变一次,如果返回的还是当前的promise,那不管调用多少次then,获取的还是老的promise的状态和当前值,这样链式调用也就没有意义了
源代码如下:(除了3.1没有实现,其他都实现了)
class Promise {
constructor(executor) {
this.status = PENDING // 当前promise的状态
this.value = undefined // 成功态对应的value
this.reason = undefined // 失败态对应的reason
this.onResolvedCallbacks = [] // 存储then函数的成功回调
this.onRejectedCallbacks = [] // 存储then函数的失败回调
/*
* 只有当状态为pending的时候才能够转换状态
*/
const resolve = value => {
if(this.status === PENDING) {
this.status = RESOLVED
this.value = value
/*
* 状态变为resolved之后,依次执行保存的成功回调
* */
this.onResolvedCallbacks.forEach(fn => fn())
}
}
const reject = reason => {
if(this.status === PENDING) {
this.status = REJECTED
this.reason = reason
/*
* 状态变为rejected之后,依次执行保存的失败回调
* */
this.onRejectedCallbacks.forEach(fn => fn())
}
}
try {
executor(resolve, reject)
}catch(e) {
reject(e)
}
}
/*
* onFulfilled: 一定是在promise是resolved状态后调用,并且接受一个参数 value
* onRejected: 一定在 promise是rejected状态后调用,并且接受一个参数 reason
* */
then(onFulfilled, onRejected) {
/*
* 兼容一下没有传onFulfilled/onRejected的情况
* 注意一下:
* onRejected如果没有传,
* 默认返回reason => { throw reason }而不是 reason => reason
* 因为要将错误传递到下一个then的onRejected,所以要抛出错误,才能走到下一个then的onRejected
* 不然就将错误当作value传递个下一个then的onFulfilled了,这是不对的
* */
onFulfilled = typeof onFulfilled === 'function' ? onFulfilled : value => value
onRejected = typeof onRejected === 'function' ? onRejected : reason => { throw reason }
let promise2
/*
* 我们需要在then方法中返回一个新的promise
* 另外:
* 1、要获取onFulfilled的返回值,传递到返回的promise中
* 2、在执行onFulfilled函数时,可能会报错,所以要加上try catch捕获错误
* */
promise2 = new Promise((resolve, reject) => {
if(this.status === RESOLVED) {
try {
let x = onFulfilled(this.value)
resolve(x)
}catch(e) {
reject(e)
}
}
if(this.status === REJECTED) {
try {
/*
* 注意:
* 这里是resolve(x)而不是reject(x)
* */
let x = onRejected(this.reason)
resolve(x)
}catch(e) {
reject(e)
}
}
/*
* 状态为pending时,将成功和失败的回调存起来
* */
if(this.status === PENDING) {
this.onResolvedCallbacks.push(() => {
try {
let x = onFulfilled(this.value)
resolve(x)
}catch(e) {
reject(e)
}
})
this.onRejectedCallbacks.push(() => {
try {
let x = onRejected(this.reason)
resolve(x)
}catch(e) {
reject(e)
}
})
}
})
return promise2
}
}
处理onFulfilled/onRejected返回值是promise的情况
可以看到代码中有四处地方都有返回值,所以我们写一个通用方法resolvePromise来处理返回值
/*
* onFulfilled: 一定是在promise是resolved状态后调用,并且接受一个参数 value
* onRejected: 一定在 promise是rejected状态后调用,并且接受一个参数 reason
* */
then(onFulfilled, onRejected) {
/*
* 兼容一下没有传onFulfilled/onRejected的情况
* 注意一下:
* onRejected如果没有传,
* 默认返回reason => { throw reason }而不是 reason => reason
* 因为要将错误传递到下一个then的onRejected,所以要抛出错误,才能走到下一个then的onRejected
* 不然就将错误当作value传递个下一个then的onFulfilled了,这是不对的
* */
onFulfilled = typeof onFulfilled === 'function' ? onFulfilled : value => value
onRejected = typeof onRejected === 'function' ? onRejected : reason => { throw reason }
let promise2
/*
* 我们需要在then方法中返回一个新的promise
* 另外:
* 1、要获取onFulfilled的返回值,传递到返回的promise中
* 2、在执行onFulfilled函数时,可能会报错,所以要加上try catch捕获错误
* */
promise2 = new Promise((resolve, reject) => {
if(this.status === RESOLVED) {
try {
let x = onFulfilled(this.value)
resolvePromise(promise2, x, resolve, reject)
}catch(e) {
reject(e)
}
}
if(this.status === REJECTED) {
try {
/*
* 注意:
* 这里是resolve(x)而不是reject(x)
* */
let x = onRejected(this.reason)
resolvePromise(promise2, x, resolve, reject)
}catch(e) {
reject(e)
}
}
/*
* 状态为pending时,将成功和失败的回调存起来
* */
if(this.status === PENDING) {
this.onResolvedCallbacks.push(() => {
try {
let x = onFulfilled(this.value)
resolvePromise(promise2, x, resolve, reject)
}catch(e) {
reject(e)
}
})
this.onRejectedCallbacks.push(() => {
try {
let x = onRejected(this.reason)
resolvePromise(promise2, x, resolve, reject)
}catch(e) {
reject(e)
}
})
}
})
return promise2
}
现在的源代码中存在一定问题
测试代码:
const p1 = new Promise((resolve, reject) => {
resolve(100)
})
p1.then(res => {
console.log(res);
}, err => {
console.log(err);
})
我们在resolvePromise中添加打印信息
/*resolvePromise*/
const resolvePromise = (promise2, x, resolve, reject) => {
console.log(promise2, x, resolve, reject);
resolve(x)
}
// undefined undefined [Function: resolve] [Function: reject]
我们发现promise2是undefined,这是因为promise2是new Promise(executor)执行完后得到的实例,而在new Promise(executor)的时候,executor已经立即执行了,我们在executor函数中获取promise2时还没有new完,所以拿到的是undefined
解决方法:加上setTimeout,产生异步,这样等到执行resolvePromise执行时这样就能拿到promise2了,其实PromiseA+规范也是这么要求的
修改后如下:
promise2 = new Promise((resolve, reject) => {
if(this.status === RESOLVED) {
setTimeout(() => {
try {
let x = onFulfilled(this.value)
resolvePromise(promise2, x, resolve, reject)
}catch(e) {
reject(e)
}
}, 0)
}
if(this.status === REJECTED) {
setTimeout(() => {
try {
/*
* 注意:
* 这里是resolve(x)而不是reject(x)
* */
let x = onRejected(this.reason)
resolvePromise(promise2, x, resolve, reject)
}catch(e) {
reject(e)
}
}, 0)
}
/*
* 状态为pending时,将成功和失败的回调存起来
* */
if(this.status === PENDING) {
this.onResolvedCallbacks.push(() => {
setTimeout(() => {
try {
let x = onFulfilled(this.value)
resolvePromise(promise2, x, resolve, reject)
}catch(e) {
reject(e)
}
}, 0)
})
this.onRejectedCallbacks.push(() => {
setTimeout(() => {
try {
let x = onRejected(this.reason)
resolvePromise(promise2, x, resolve, reject)
}catch(e) {
reject(e)
}
}, 0)
})
}
})
这样就解决了promise2为undeinfed的问题下面可以安心编写resolvePromise方法了
resolvePromise
先看下PromiseA+规范
-
如果返回的
promise2和x是指向同一个引用(循环引用),则抛出错误 -
如果
x是一个promise实例,则采用它的状态:- 如果
x是pending状态,那么保留它(递归执行这个promise处理程序),直到pending状态转为fulfilled或rejected状态 - 如果或当
x状态是fulfilled,resolve 它,并且传入和 promise 一样的值value - 如果或当
x状态是rejected,reject 它,并且传入和 promise 一样的值reason
- 如果
-
如果 x 是个对象或函数类型
-
把
x.then赋值给then变量 -
如果捕获(try,catch)到
x.then抛出的错误的话,需要reject这个promise -
如果
then是函数类型,那个用x调用它(将 then 的 this 指向 x),第一个参数传resolvePromise,第二个参数传rejectPromise- 如果或当
resolvePromise被调用并接受一个参数y时,执行[[Resolve]](promise, y) - 如果或当
rejectPromise被调用并接受一个参数r时,执行reject(r) - 如果
resolvePromise和rejectPromise已经被调用或以相同的参数多次调用的话吗,优先第一次的调用,并且之后的调用全部被忽略(避免多次调用)
- 如果或当
-
如果
then执行过程中抛出了异常,- 如果
resolvePromise或rejectPromise已经被调用,那么忽略异常 - 否则,则
reject这个异常
- 如果
-
如果
then不是函数类型,直接resolvex(resolve(x))
-
-
如果
x即不是函数类型也不是对象类型,直接resolve x(resolve(x))
实现:
promise2和x是指向同一个引用这个是什么场景呢,如下代码:
const p = new Promise((resolve, reject) => {
resolve(1)
})
const p2 = p.then(res => {
return p2
})
p2.then(res => {
console.log(res)
}, err => {
console.log(err)
})
// 报错TypeError: Chaining cycle detected for promise #<Promise>
如上代码, p2 = p.then(res => { return p2 }),成功回调中返回的是一个promise,那么p2的状态将会等待这个promise调用resolve/reject来决定p2.then走成功回调还是失败回调,但是此时返回的是p2自己,等于是自己在等自己,但是自己又没有调用resolve/reject所以状态一直没有改变,代码就死在这里了,造成了死循环
判断是否循环引用
const resolvePromise = (promise2, x, resolve, reject) => {
if(promise2 === x) {
return reject(new TypeError('Chaining cycle detected for promise'))
}
}
对x的类型进行判断
const resolvePromise = (promise2, x, resolve, reject) => {
if(promise2 === x) {
return reject(new TypeError('Chaining cycle detected for promise'))
}
/*
* 先判断x否是对象或者函数,如果不是,说明x是原始值,直接resolve掉,是的话再进一步判断
* 获取x.then赋值给then,判断then是否是一个函数,如果不是说明x就是一个普通对象,也直接resolve掉
* 在获取x.then的时候,有可能会报错,比如这样写
* Object.defineProperty(x, 'then', {
* get() {
* throw new Error('故意刁难你')
* }
* })
* 这样在执行x.then的时候就会报错,所以要用try catch捕获错误
* 如果then是一个函数,我们认为x是一个promise,然后执行then并把x作为this传进去
* 如果不指定this,那么promise内部获取this.value/this.reason/this.status就获取不到
* 执行的then其实和平常使用.then一样 p.then(res => {}, err => {}),只不过使用call指定了this而已
*/
if((typeof x === 'object' || typeof x === 'function') && x !== null) {
try {
const then = x.then
if(typeof then === 'function') {
then.call(x, y => {
// y就是传递给onFulfilled函数的参数
resolve(y)
}, r => {
// r就是传递给onRejected函数的参数
reject(r)
})
}else {
resolve(x)
}
}catch (e) {
reject(e)
}
}else {
resolve(x)
}
}
上面在then函数成功回调的时候,直接resolve(y),有一些问题
比如:
const p = new Promise((resolve, reject) => {
resolve(1)
})
const p2 = p.then(res => {
return new Promise((resolve, reject) => {
resolve(new Promise((resolve, reject) => {
resolve(new Promise((resolve, reject) => {
resolve(res)
}))
}))
})
})
p2.then(res => {
console.log(res)
})
/*
* 原生的promise打印1
* 而现在自己写的打印的是一个Promise对象
* 在这里我们返回了一个promise实例,其中resolve了一个新的promise实例,调用then的时候,
* 接收的参数y是这个新的promise实例,直接resolve的话就不太对了,在这里我们做一些修改
*/
修改后的代码
then.call(x, y => {
/*
* 这里相当于做一个递归调用
* 如果then方法成功回调接收的是promise,就再次调用resolvePromise方法
* 直到获取到的值是普通值,在将这个值resolve掉
*/
resolvePromise(promise2, y, resolve, reject)
}, r => {
// r就是传递给onRejected函数的参数
reject(r)
})
还有一个问题,resolvePromise,这个函数是所有promise通用的,但是别人的promise,有可能既会调resolve也会调reject,那么就会出问题了,所以我们接下来要做一下限制
let called;
if ((typeof x === 'object' || typeof x === 'function') && x !== null) {
try {
const then = x.then
if (typeof then === 'function') {
/*
* 别人的promise可能在执行resolve后又执行reject,
* 所以这里用一个变量来限制,保证成功/失败回调只会调用一次
*/
then.call(x, y => {
if(called) return
called = true
resolvePromise(promise2, y, resolve, reject)
}, r => {
if(called) return
called = true
reject(r)
})
} else {
resolve(x)
}
} catch (e) {
if(called) return
called = true
reject(e)
}
} else {
resolve(x)
}
到这里差不多就写完了,但是还有一点小问题,比如运行如下代码:
const p1 = new Promise((resolve, reject) => {
resolve(new Promise((resolve, reject) => {
resolve(new Promise((resolve, reject) => {
resolve(2)
}))
}))
})
p1.then(res => {
console.log(res, 'res')
}, err => {
console.log(err, 'err')
})
结果:
原生Promise打印的是2,我们自己写的打印的是Promise实例对象,这是因为resolve一个promise实例,在代码的resolve方法中,我们直接把这个值赋给了value,所以打印出来的不是promise执行后的结果,所以在resolve方法中需要做个判断,如果resolve函数传入的值是promise就直接执行这个promise的then方法
const resolve = value => {
if(value instanceof Promise) {
return value.then(resolve, reject)
}
if (this.status === PENDING) {
this.status = RESOLVED
this.value = value
/*
* 状态变为resolved之后,依次执行保存的成功回调
* */
this.onResolvedCallbacks.forEach(fn => fn())
}
}
最后完整代码如下:
const PENDING = 'pending',
RESOLVED = 'resolved',
REJECTED = 'rejected'
const resolvePromise = (promise2, x, resolve, reject) => {
if (promise2 === x) {
return reject(new TypeError('Chaining cycle detected for promise'))
}
/*
* 先判断x否是对象或者函数,如果不是,说明x是原始值,直接resolve掉,是的话再进一步判断
* 获取x.then赋值给then,判断then是否是一个函数,如果不是说明x就是一个普通对象,也直接resolve掉
* 在获取x.then的时候,有可能会报错,比如这样写
* Object.defineProperty(x, 'then', {
* get() {
* throw new Error('故意刁难你')
* }
* })
* 这样在执行x.then的时候就会报错,所以要用try catch捕获错误
* 如果then是一个函数,我们认为x是一个promise,然后执行then并把x作为this传进去
* 如果不指定this,那么promise内部获取this.value/this.reason/this.status就获取不到
* 执行的then其实和平常使用.then一样 p.then(res => {}, err => {}),只不过使用call指定了this而已
*/
let called;
if ((typeof x === 'object' || typeof x === 'function') && x !== null) {
try {
const then = x.then
if (typeof then === 'function') {
then.call(x, y => {
if(called) return
called = true
resolvePromise(promise2, y, resolve, reject)
}, r => {
if(called) return
called = true
reject(r)
})
} else {
resolve(x)
}
} catch (e) {
if(called) return
called = true
reject(e)
}
} else {
resolve(x)
}
}
class Promise {
constructor(executor) {
this.status = PENDING // 当前promise的状态
this.value = undefined // 成功态对应的value
this.reason = undefined // 失败态对应的reason
this.onResolvedCallbacks = [] // 存储then函数的成功回调
this.onRejectedCallbacks = [] // 存储then函数的失败回调
/*
* 只有当状态为pending的时候才能够转换状态
*/
const resolve = value => {
if(value instanceof Promise) {
return value.then(resolve, reject)
}
if (this.status === PENDING) {
this.status = RESOLVED
this.value = value
/*
* 状态变为resolved之后,依次执行保存的成功回调
* */
this.onResolvedCallbacks.forEach(fn => fn())
}
}
const reject = reason => {
if (this.status === PENDING) {
this.status = REJECTED
this.reason = reason
/*
* 状态变为rejected之后,依次执行保存的失败回调
* */
this.onRejectedCallbacks.forEach(fn => fn())
}
}
try {
executor(resolve, reject)
} catch (e) {
reject(e)
}
}
/*
* onFulfilled: 一定是在promise是resolved状态后调用,并且接受一个参数 value
* onRejected: 一定在 promise是rejected状态后调用,并且接受一个参数 reason
* */
then(onFulfilled, onRejected) {
/*
* 兼容一下没有传onFulfilled/onRejected的情况
* 注意一下:
* onRejected如果没有传,
* 默认返回reason => { throw reason }而不是 reason => reason
* 因为要将错误传递到下一个then的onRejected,所以要抛出错误,才能走到下一个then的onRejected
* 不然就将错误当作value传递个下一个then的onFulfilled了,这是不对的
* */
onFulfilled = typeof onFulfilled === 'function' ? onFulfilled : value => value
onRejected = typeof onRejected === 'function' ? onRejected : reason => {
throw reason
}
let promise2
/*
* 我们需要在then方法中返回一个新的promise
* 另外:
* 1、要获取onFulfilled的返回值,传递到返回的promise中
* 2、在执行onFulfilled函数时,可能会报错,所以要加上try catch捕获错误
* */
promise2 = new Promise((resolve, reject) => {
if (this.status === RESOLVED) {
setTimeout(() => {
try {
let x = onFulfilled(this.value)
resolvePromise(promise2, x, resolve, reject)
} catch (e) {
reject(e)
}
}, 0)
}
if (this.status === REJECTED) {
setTimeout(() => {
try {
/*
* 注意:
* 这里是resolve(x)而不是reject(x)
* */
let x = onRejected(this.reason)
resolvePromise(promise2, x, resolve, reject)
} catch (e) {
reject(e)
}
}, 0)
}
/*
* 状态为pending时,将成功和失败的回调存起来
* */
if (this.status === PENDING) {
this.onResolvedCallbacks.push(() => {
setTimeout(() => {
try {
let x = onFulfilled(this.value)
resolvePromise(promise2, x, resolve, reject)
} catch (e) {
reject(e)
}
}, 0)
})
this.onRejectedCallbacks.push(() => {
setTimeout(() => {
try {
let x = onRejected(this.reason)
resolvePromise(promise2, x, resolve, reject)
} catch (e) {
reject(e)
}
}, 0)
})
}
})
return promise2
}
}
module.exports = Promise
测试
在导出前加一段测试代码
Promise.defer = Promise.deferred = function(){
let dfd = {};
dfd.promise = new Promise((resolve,reject)=>{
dfd.resolve = resolve;
dfd.reject = reject;
})
return dfd;
}
module.exports = Promise
通过promises-aplus-tests可以测试我们实现的Promise类是否满足Promise/A+规范
npx promises-aplus-tests Promise.js
以上结果就代表通过测试,至此就完整实现了一个符合PromiseA+规范的Promise类