Promise是ES6新增为了解决异步编程的一种实现方案,配合
async
和awiat
可以做到更加优雅的书写异步任务并且实现同步执行。Promise意为承诺,承诺会在未来某个时间返回操作的结果
Promise几个简单示例:
let p = new Promise((resolve, reject) => {
console.log(1);
setTimeout(() => {
resolve('then');
}, 3000);
});
let p1 = new Promise(); // TypeError: Promise resolver undefined is not a function
p.then(res => console.log(1)); // '1', 3s -> 'then'
这个实例可以得到Promise的以下特点:
-
new Promise
后会立即执行,并且接收一个必传
函数作为参数 -
接收的函数中有2个参数
-
值需要使用
then
方法获取
let p2 = new Promise((resolve, reject) => {
resolve('成功');
reject('失败');
})
console.log('p2', p2); // { PromiseState: 'fulfilled', PromiseResult: '成功' }
let p3 = new Promise((resolve, reject) => {
reject('失败')
resolve('成功')
})
console.log('p3', p3); // { PromiseState: 'rejected', PromiseResult: '失败' }
let p4 = new Promise((resolve, reject) => {
throw('报错'); // { PromiseState: 'rejected', PromiseResult: '失败' }
})
console.log('p4', p4);
这个实例可以得到Promise的以下特点:
- 有三种状态:初始
pending
,成功fullfilled
,拒绝rejected
,并且状态只能从pending
转变为fulfilled
或者rejected
,不可逆 resolve
将状态转变为fulfilled
,reject
将状态转变为rejected
- 一旦状态从
pending
转变为fulfilled
或者rejected
就不会再改变了
1、根据前面的总结定义好初始结构
// 定义promise的状态
const PENDING = 'pending';
const FULLFILLED = 'fullfilled';
const REJECTED = 'rejected';
class _Promise {
// 接收一个函数作为参数
constructor(executor) {
// 初始状态为pending
this.status = PENDING;
// new Promise后立即执行,接收2个参数
executor(resolve, reject);
}
// 获取结果的函数
then() {}
}
根据第二个示例我们可以看到p3
中抛出错误也是被rejected
的,所以优化下结构:
const PENDING = 'pending';
const FULLFILLED = 'fullfilled';
const REJECTED = 'rejected';
class _Promise {
constructor(executor) {
this.status = PENDING;
// 新增try-catch捕获错误,出错时将状态转变为rejected
+ try {
executor(resolve, reject);
+ } catch (error) {
reject(error);
+ }
}
then() {}
}
2、实现resolve、reject方法
在前面的示例中已经知道promise
传入的函数接收2个参数,也就是resolve
和reject
,他们的作用就是改变promise
的状态。
const PENDING = 'pending';
const FULLFILLED = 'fullfilled';
const REJECTED = 'rejected';
class _Promise {
constructor(executor) {
this.status = PENDING;
try {
+ executor(this.resolve.bind(this), this.reject.bind(this));
} catch (error) {
this.reject(error);
}
}
+ resolve() {}
+ reject() {}
then() {}
}
状态只能从pending
转变为fullfilled
和rejected
,并且不可逆:
const PENDING = 'pending';
const FULLFILLED = 'fullfilled';
const REJECTED = 'rejected';
class _Promise {
constructor(executor) {
this.status = PENDING;
try {
executor(this.resolve, this.reject);
} catch (error) {
this.reject(error);
}
}
resolve() {
// 状态为pending才改变状态
+ if (this.status === PENDING) {
+ this.status = FULLFILLED;
+ }
}
reject() {
// 状态为pending才改变状态
+ if (this.status === PENDING) {
+ this.status = REJECTED;
+ }
}
then() {}
}
根据示例可以看到调用resolve
和reject
时可以传递参数,最后可以通过调用then
获取结果。
const PENDING = 'pending';
const FULLFILLED = 'fullfilled';
const REJECTED = 'rejected';
class _Promise {
constructor(executor) {
this.status = PENDING;
// 保存结果,最终返回
+ this.value = null;
try {
executor(this.resolve, this.reject);
} catch (error) {
this.reject(error);
}
}
+ resolve(value) {
// 状态为pending才改变状态
if (this.status === PENDING) {
this.status = FULLFILLED;
+ this.value = value;
}
}
+ reject(reason) {
// 状态为pending才改变状态
if (this.status === PENDING) {
this.status = REJECTED;
+ this.value = reason;
}
}
then() {}
}
3、实现then方法
then方法返回一个Promise。它最多需要两个参数:Promise的成功和失败情况的回调函数(失败情况的回调函数为可选)——MDN
// 接收两个参数
then(onFullfilled, onRejected) {
// 返回一个Promise
return new _Promise((resolve, reject) => {});
}
因为then
方法返回了promise
,而promise
上又有then
方法,所以可以链式调用,例如:
let p = new Promise((resolve, reject) => {
resolve(1);
});
p.then(res => {
console.log(res);
return res += 1;
}).then(res => {
console.log(res);
return res *= res;
}).then(res => {
console.log(res);
}); // 1,2,4
先看下原生方法的执行结果:
let p = new Promise((resolve, reject) => {
resolve('成功');
reject('失败');
});
p.then(
res => console.log(res),
error => console.log(error)
); // 成功
// 反过来
let p = new Promise((resolve, reject) => {
reject('失败');
resolve('成功');
});
p.then(
res => console.log(res),
error => console.log(error)
); // 失败
new Promise
时接收2个参数,分别为将状态转变为fullfilled
和rejected
的回调函数。而then
方法也是接收2个参数,分别为promise
的成功和失败情况的回调函数。所以根据结果可以知道then
方法就是在根据promise
的状态执行对应的方法
// 接收两个参数
then(onFullfilled, onRejected) {
// 如果状态为fullfilled,调用成功回调并将resolve时带来的参数传入并执行
+ if (this.status === FULLFILLED) {
+ onFullfilled(this.value);
+ }
// 如果状态为rejected,调用失败回调并将reject时带来的参数传入并执行
+ if (this.status === REJECTED) {
+ onRejected(this.value);
+ }
// 返回一个Promise
return new _Promise((resolve, reject) => {});
}
暂时基本功能都有了,进行一下测试:
const PENDING = 'pending';
const FULLFILLED = 'fullfilled';
const REJECTED = 'rejected';
class _Promise {
constructor(executor) {
this.status = PENDING;
this.value = null;
try {
executor(this.resolve.bind(this), this.reject.bind(this));
} catch (error) {
this.reject(error);
}
}
resolve(value) {
if (this.status === PENDING) {
this.status = FULLFILLED;
this.value = value;
}
}
reject(reason) {
if (this.status === PENDING) {
this.status = REJECTED;
this.value = reason;
}
}
then(onFullfilled, onRejected) {
if (this.status === FULLFILLED) {
onFullfilled(this.value);
}
if (this.status === REJECTED) {
onRejected(this.value);
}
return new _Promise((resolve, reject) => {});
}
}
// 测试代码
let p = new _Promise((resolve, reject) => {
resolve('成功');
reject('失败');
});
p.then(
res => console.log(res),
error => console.log(error)
); // 成功
// 反过来
let p = new _Promise((resolve, reject) => {
reject('失败');
resolve('成功');
});
p.then(
res => console.log(res),
error => console.log(error)
); // 失败
和原生执行一样,成功!但是,忽略了一些细节,比如:
// 原生
let p = new Promise((resolve, reject) => {
resolve('成功');
})
p.then(
null, // 或undefined
error => console.log(error)
); // 无输出无报错
// 自己实现的
let p = new _Promise(resolve => {
resolve('成功');
});
p.then(
null,
error => console.log(error)
); // onFullfilled is not a function
因为我们在then
方法中实现是直接执行传入的函数,当这个参数不是函数因为没有做处理,把不是函数的参数当做函数执行自然就会报错,所以在then
函数中给参数加个处理
then(onFullfilled, onRejected) {
// 判断如果传入的参数类型不为function,就给它赋值为一个函数
+ onFullfilled = typeof onFullfilled === 'function' ? onFullfilled : value => value;
+ onRejected = typeof onRejected === 'function' ? onRejected : error => { throw Error(error) }
if (this.status === FULLFILLED) {
onFullfilled(this.value);
}
if (this.status === REJECTED) {
onRejected(this.value);
}
return new _Promise((resolve, reject) => {});
}
修改后再次执行之前的代码,发现就没有报错了
4、实现异步
到目前为止,代码里可以看到没有任何的特殊的东西,也就是说代码会正常按顺序同步执行。但是实际上不可能是都按照顺序同步执行的。众所周知JavaScript
有个事件循环机制,将事件分为了同步任务
和异步任务
两大类,接下来就要对异步任务
进行处理,为什么呢?举个例子:
// 原生
console.log(1);
let p = new Promise((resolve, reject) => {
console.log(2);
resolve(4);
});
p.then(res => console.log(res));
console.log(3);
// 输出1,2,3,4
// 应用到自己实现的上
console.log(1);
let p = new _Promise((resolve, reject) => {
console.log(2);
resolve(4);
});
p.then(res => console.log(res));
console.log(3);
// 输出1,2,4,3
在MDN有说明,promise
的操作会被视为异步执行,所有的promise
都是异步的,并且和setTimeout(action, 10)
特别相似。那么我们就用``setTimeout`来模拟异步。
then(onFullfilled, onRejected) {
onFullfilled = typeof onFullfilled === 'function' ? onFullfilled : value => value;
onRejected = typeof onRejected === 'function' ? onRejected : error => { throw Error(error) }
if (this.status === FULLFILLED) {
+ setTimeout(() => {
onFullfilled(this.value);
+ });
}
if (this.status === REJECTED) {
+ setTimeout(() => {
onRejected(this.value);
+ });
}
return new _Promise((resolve, reject) => {});
}
重新执行一下之前的代码,发现输出顺序就已经正确输出1,2,3,4了
5、处理收集回调
根据上一步骤可以知道promise
和它的操作都是异步的。那么有怎么一种情况,我在promise
里也写异步事件会怎么样呢。如果了解了事件循环
的话应该会知道,这里暂且提一嘴
// 原生
console.log(1);
let p = new Promise((resolve, reject) => {
console.log(2);
setTimeout(() => {
console.log(4);
resolve(5);
}, 1000);
});
p.then(res => console.log(res));
console.log(3);
用事件循环
解释一下上面代码执行的过程:
- 执行同步任务
console.log(1);
,输出"1" new Promise()
立即执行,执行同步任务console.log(2);
并输出"2",遇见异步任务setTimeout
加入到宏任务队列(异步任务分为宏任务和微任务,promise的回调
为微任务)- 遇到
p.then()
,将其回调加入到微任务队列 - 执行同步任务
console.log(3);
并输出"3" - 主线程执行栈清空,去寻找异步任务执行,发现同时存在宏任务和微任务,先执行微任务
- 执行微任务
then
回调,此时promise
状态为pending
不执行 - 执行同步任务
console.log(4);
并输出"4" - 微任务执行完毕执行宏任务,执行同步任务
console.log(4);
并输出"4" - 调用
resolve(5);
,此时promise
状态改变,执行对应的回调,输出"5"
所以输出为:1,2,3,4,5
去_promise`上去,查看执行结果:
console.log(1);
let p = new _Promise((resolve, reject) => {
console.log(2);
setTimeout(() => {
console.log(4);
resolve(5);
}, 1000);
});
p.then(res => console.log(res));
console.log(3);
// 输出1,2,3,4
发现执行结果少输出一个5,而5是执行then
的回调打印的,那么可以猜测是then
没有被执行。而我们的then
中执行是进行了状态判断的,也就是说只有当promise
状态为FULLFILLED
或者REJECTED
时才会执行。打印一下执行时的status
看看是不是它的问题
console.log(1);
let p = new _Promise((resolve, reject) => {
console.log(2);
setTimeout(() => {
console.log(4);
console.log(p.status);
resolve(5);
console.log(p.status);
}, 1000);
});
p.then(res => console.log(res));
console.log(3);
// 输出1,2,3,4,pending,fullfilled
继续用事件循环
来梳理下执行过程:
- 执行同步任务
console.log(1)
,输出"1" new Promise()
立即执行,执行同步任务console.log(2);
,输出"2"- 遇到异步任务
setTimeout
加入到宏任务队列 - 遇到异步任务
then回调
,加入到微任务队列 - 执行同步任务
console.log(3);
,并输出"3" - 主线程执行栈清空,去寻找异步任务执行,发现同时存在宏任务和微任务,先执行微任务
- 执行微任务
then
回调,此时promise
状态为pending
没有执行结果 - 微任务执行完毕执行宏任务,执行同步任务
console.log(4);
并输出"4" - 执行
console.log(p.status);
,输出"pending" - 执行
resolve(5);
,promise
状态改变为fullfilled
- 执行
console.log(p.status);
,输出"fullfilled"
观察执行过程可以发现,当promise
的状态为pending
时,自己实现的then
方法中是没有做对应处理的。可能这就是导致了没有执行的问题。那么当状态为pending
时我们应该做什么呢?
then(onFullfilled, onRejected) {
onFullfilled = typeof onFullfilled === 'function' ? onFullfilled : value => value;
onRejected = typeof onRejected === 'function' ? onRejected : error => { throw Error(error) }
+ if (this.status === PENDING) {
// TODO: 状态为pending时应该做什么
+ }
if (this.status === FULLFILLED) {
setTimeout(() => {
onFullfilled(this.value);
});
}
if (this.status === REJECTED) {
setTimeout(() => {
onRejected(this.value);
});
}
return new _Promise((resolve, reject) => {});
}
这里继续以执行顺序来理解。then
函数是同步执行的,而获得结果是需要调用resolve
或者reject
的。那么我们怎么样才能保证then方法在获取到结果后才执行呢?解决办法就是
收集回调`。
在promise
的状态为pending
时,我们先将回调收集起来,等到执行resolve
或者reject
时,将对应的回调取出来一并执行。
1、创建数组收集回调,毕竟回调可能有多个
class _Promise {
constructor(executor) {
this.status = PENDING;
this.value = null;
// 收集成功的回调
+ this.fullfilledCallbacks = [];
// 收集失败的回调
+ this.rejectedCallbacks = [];
try {
executor(this.resolve.bind(this), this.reject.bind(this));
} catch (error) {
this.reject(error);
}
}
}
2、在then方法中收集回调
then(onFullfilled, onRejected) {
onFullfilled = typeof onFullfilled === 'function' ? onFullfilled : value => value;
onRejected = typeof onRejected === 'function' ? onRejected : error => { throw Error(error) }
// 状态为pending时收集依赖
if (this.status === PENDING) {
+ this.fullfilledCallbacks.push(onFullfilled);
+ this.rejectedCallbacks.push(onRejected);
}
if (this.status === FULLFILLED) {
setTimeout(() => {
onFullfilled(this.value);
});
}
if (this.status === REJECTED) {
setTimeout(() => {
onRejected(this.value);
});
}
return new _Promise((resolve, reject) => {});
}
3、resolve和reject方法中执行回调
在执行resolve()
或者reject()
时,会遍历保存的对应的回调数组(在执行then
时保存的),并将参数传入执行。
resolve(value) {
if (this.status === PENDING) {
this.status = FULLFILLED;
this.value = value;
// 执行收集的回调
+ this.fullfilledCallbacks.forEach(callback => callback(value));
}
}
reject(reason) {
if (this.status === PENDING) {
this.status = REJECTED;
this.value = reason;
// 执行收集的回调
+ this.rejectedCallbacks.forEach(callback => callback(reason));
}
}
整体代码如下:
const PENDING = 'pending';
const FULLFILLED = 'fullfilled';
const REJECTED = 'rejected';
class _Promise {
constructor(executor) {
this.status = PENDING;
this.value = null;
this.fullfilledCallbacks = [];
this.rejectedCallbacks = [];
try {
executor(this.resolve.bind(this), this.reject.bind(this));
} catch (error) {
this.reject(error);
}
}
resolve(value) {
if (this.status === PENDING) {
this.status = FULLFILLED;
this.value = value;
this.fullfilledCallbacks.forEach(callback => callback(value));
}
}
reject(reason) {
if (this.status === PENDING) {
this.status = REJECTED;
this.value = reason;
this.rejectedCallbacks.forEach(callback => callback(reason));
}
}
then(onFullfilled, onRejected) {
onFullfilled = typeof onFullfilled === 'function' ? onFullfilled : value => value;
onRejected = typeof onRejected === 'function' ? onRejected : error => { throw Error(error) }
if (this.status === PENDING) {
this.fullfilledCallbacks.push(onFullfilled);
this.rejectedCallbacks.push(onRejected);
}
if (this.status === FULLFILLED) {
setTimeout(() => {
onFullfilled(this.value);
});
}
if (this.status === REJECTED) {
setTimeout(() => {
onRejected(this.value);
});
}
return new _Promise((resolve, reject) => {});
}
}
再次执行之前测试的代码,发现then
函数的回调触发了。但是细心点还是可以发现,在打印promise
状态之后同步执行了resolve
并触发了回调,这明显是不对的,我们期望的是resolve
和reject
是异步执行的。所以这里使用setTimeout
来模拟异步
resolve(value) {
if (this.status === PENDING) {
+ setTimeout(() => {
this.status = FULLFILLED;
this.value = value;
this.fullfilledCallbacks.forEach(callback => callback(value));
+ });
}
}
reject(reason) {
if (this.status === PENDING) {
+ setTimeout(() => {
this.status = REJECTED;
this.value = reason;
this.rejectedCallbacks.forEach(callback => callback(reason));
+ });
}
}
再次测试输出结果,就会发现输出和原生一致了
4、测试多次执行then方法
原生promise
可以多次调用then
,同样的也给自己实现的进行一下测试
// 原生
const p = new Promise((resolve, reject) => {
setTimeout(() => {
resolve('success')
}, 2000);
})
p.then(value => {
console.log(1)
console.log('resolve', value)
})
p.then(value => {
console.log(2)
console.log('resolve', value)
})
p.then(value => {
console.log(3)
console.log('resolve', value)
})
// 1 resolve success 2 resolve success 3 resolve success
// 自己实现的
const p = new _Promise((resolve, reject) => {
setTimeout(() => {
resolve('success')
}, 2000);
})
p.then(value => {
console.log(1)
console.log('resolve', value)
})
p.then(value => {
console.log(2)
console.log('resolve', value)
})
p.then(value => {
console.log(3)
console.log('resolve', value)
})
// 1 resolve success 2 resolve success 3 resolve success
没有问题,基本大功告成!剩下最后的promise链式调用
6、实现链式调用
首先用一个简单示例解释一下什么是链式调用
class Person {
constructor() {
this.name = '';
}
setName(name) {
this.name = name;
return this;
}
sayHello() {
console.log(`hello,我叫${this.name}`);
return this;
}
}
// 使用
let p = new Person();
p.setName('哈哈哈').sayHello(); // hello,我叫哈哈哈
链式调用的核心就是上面的return this
。当我们调用p.setName()
时会返回自身实例,而实例上存在setName
和sayHello
两个方法,所以就能一直.setName()
或者.sayHello()
调用下去。
回到我们的then
方法会发现在之前已经提前返回了一个new _Promise()
。因为Promise
要求then
返回一个promise
。所以这就是then
方法能够链式调用的原因。还不明白可以认真立即上面这段话。
扩展:在以前使用Ajax发送请求时也会存在then回调,并且会出现因为then的无限嵌套回调而出现的回调地狱,解决办法就是使用基于Promise的
async
和await
语法糖
在原生Promise
中我们是这样使用链式调用的:
let p = new Promise((resolve, reject) => {
resolve(1);
});
p.then(res => {
console.log(res);
return res + 1;
}).then(res => {
console.log(res);
});
// 1,2
将同样的代码运用到自己实现的_Promise
上后会发现有问题,因为我们then
方法还没有完善,返回的_Promise
里什么都没有。那么接下来就完善这个then
方法。
1、首先将内容移动到返回的Promise中去
then(onFullfilled, onRejected) {
onFullfilled = typeof onFullfilled === 'function' ? onFullfilled : value => value;
onRejected = typeof onRejected === 'function' ? onRejected : error => { throw Error(error) }
return new _Promise((resolve, reject) => {
if (this.status === PENDING) {
this.fullfilledCallbacks.push(onFullfilled);
this.rejectedCallbacks.push(onRejected);
}
if (this.status === FULLFILLED) {
setTimeout(() => {
onFullfilled(this.value);
});
}
if (this.status === REJECTED) {
setTimeout(() => {
onRejected(this.value);
});
}
});
}
}
2、封装处理Promise返回内容的函数
function resolvePromise(promise2, x, resolve, reject) {
// 不能返回自身
if (x === promise2) {
throw Error('不能返回自身');
}
// 如果是Promise
if (x instanceof _Promise) {
// 状态为pending
if (x.status === PENDING) {
// 收集回调等待执行
x.then(
y => resolvePromise(promise2, y, resolve, reject),
reject
)
// 状态为fullfilled,调用resolve执行
} else if (x.status === FULLFILLED) {
resolve(x.value);
// 状态为rejected,调用reject执行
} else {
reject(x.value);
}
// 如果是thenable对象(具有then属性)
} else if (x !== null && (typeof x === 'object' || typeof x === 'function')) {
let then = null;
try {
// 有then属性,赋值
then = x.then;
} catch (error) {
// 获取不到then报错就调用reject
reject(error);
}
// 如果then是个函数,就以promise相同方式调用
if (typeof then === 'function') {
let called = false; // 避免多次调用
try {
then.call(
x,
res => {
if (called) {
return;
}
called = true;
resolvePromise(promise2, res, resolve, reject);
},
error => {
// 防止多次调用
if (called) {
return;
}
called = true;
// 出错就调用reject
reject(error);
}
)
} catch (error) {
// 防止多次调用
if (called) {
return;
}
called = true;
// 出错就调用reject
reject(error);
}
} else {
// 否则就是个正常值,执行调用resolve
resolve(x);
}
// 否则直接调用resolve
} else {
resolve(x);
}
}
3、修改then方法中的逻辑
then(onFullfilled, onRejected) {
onFullfilled = typeof onFullfilled === 'function' ? onFullfilled : value => value;
onRejected = typeof onRejected === 'function' ? onRejected : error => { throw Error(error) }
let promise2 = new _Promise((resolve, reject) => {
if (this.status === PENDING) {
this.fullfilledCallbacks.push(() => {
try {
// 获取第一次promise执行后的值
let x = onFullfilled(this.value);
// 使用封装的方法处理返回内容
resolvePromise(promise2, x, resolve, reject);
} catch (error) {
// 遇到错误就调用reject
reject(error);
}
});
this.rejectedCallbacks.push(() => {
try {
// 获取第一次promise执行后的值
let x = onRejected(this.value);
// 使用封装的方法处理返回内容
resolvePromise(promise2, x, resolve, reject);
} catch (error) {
// 遇到错误就调用reject
reject(error);
}
});
}
if (this.status === FULLFILLED) {
setTimeout(() => {
try {
// 获取第一次promise执行后的值
let x = onFullfilled(this.value);
// 使用封装的方法处理返回内容
resolvePromise(promise2, x, resolve, reject);
} catch (error) {
// 遇到错误就调用reject
reject(error);
}
});
}
if (this.status === REJECTED) {
setTimeout(() => {
try {
// 获取第一次promise执行后的值
let x = onRejected(this.value);
// 使用封装的方法处理返回内容
resolvePromise(promise2, x, resolve, reject);
} catch (error) {
// 遇到错误就调用reject
reject(error);
}
});
}
});
return promise2;
}
接下来进行测试:(随便找的一个例子)
// 原生
const p1 = new Promise((resolve, reject) => {
resolve(1); // 同步executor测试
})
p1.then(res => {
console.log(res);
return 2; // 链式调用测试
}).then() // 值穿透测试
.then(res => {
console.log(res);
return new Promise((resolve, reject) => {
resolve(3); // 返回Promise测试
})
})
.then(res => {
console.log(res);
throw new Error('reject测试') // reject测试
})
.then(() => { }, err => {
console.log(err);
})
// 输出:1,2,3,Error: reject测试
// 自己实现的_Promise
const p1 = new _Promise((resolve, reject) => {
resolve(1); // 同步executor测试
})
p1.then(res => {
console.log(res);
return 2; // 链式调用测试
}).then() // 值穿透测试
.then(res => {
console.log(res);
return new _Promise((resolve, reject) => {
resolve(3); // 返回Promise测试
})
})
.then(res => {
console.log(res);
throw new Error('reject测试') // reject测试
})
.then(() => { }, err => {
console.log(err);
})
// 输出:1,2,3,Error: reject测试
至此,已经根据原生实现了一个自己的Promise
完整代码:
const PENDING = 'pending';
const FULLFILLED = 'fullfilled';
const REJECTED = 'rejected';
function resolvePromise(promise2, x, resolve, reject) {
if (x === promise2) {
throw Error('不能返回自身');
}
if (x instanceof _Promise) {
if (x.status === PENDING) {
x.then(
y => resolvePromise(promise2, y, resolve, reject),
reject
)
} else if (x.status === FULLFILLED) {
resolve(x.value);
} else {
reject(x.value);
}
} else if (x !== null && (typeof x === 'object' || typeof x === 'function')) {
let then = null;
try {
then = x.then;
} catch (error) {
reject(error);
}
if (typeof then === 'function') {
let called = false;
try {
then.call(
x,
res => {
if (called) {
return;
}
called = true;
resolvePromise(promise2, res, resolve, reject);
},
error => {
if (called) {
return;
}
called = true;
reject(error);
}
)
} catch (error) {
if (called) {
return;
}
called = true;
reject(error);
}
} else {
resolve(x);
}
} else {
resolve(x);
}
}
class _Promise {
constructor(executor) {
this.status = PENDING;
this.value = null;
this.fullfilledCallbacks = [];
this.rejectedCallbacks = [];
try {
executor(this.resolve.bind(this), this.reject.bind(this));
} catch (error) {
this.reject(error);
}
}
resolve(value) {
if (this.status === PENDING) {
setTimeout(() => {
this.status = FULLFILLED;
this.value = value;
this.fullfilledCallbacks.forEach(callback => callback(value));
})
}
}
reject(reason) {
if (this.status === PENDING) {
setTimeout(() => {
this.status = REJECTED;
this.value = reason;
this.rejectedCallbacks.forEach(callback => callback(reason));
})
}
}
then(onFullfilled, onRejected) {
onFullfilled = typeof onFullfilled === 'function' ? onFullfilled : value => value;
onRejected = typeof onRejected === 'function' ? onRejected : error => { throw Error(error) }
let promise2 = new _Promise((resolve, reject) => {
if (this.status === PENDING) {
this.fullfilledCallbacks.push(() => {
try {
let x = onFullfilled(this.value);
resolvePromise(promise2, x, resolve, reject);
} catch (error) {
reject(error);
}
});
this.rejectedCallbacks.push(() => {
try {
let x = onRejected(this.value);
resolvePromise(promise2, x, resolve, reject);
} catch (error) {
reject(error);
}
});
}
if (this.status === FULLFILLED) {
setTimeout(() => {
try {
let x = onFullfilled(this.value);
resolvePromise(promise2, x, resolve, reject);
} catch (error) {
reject(error);
}
});
}
if (this.status === REJECTED) {
setTimeout(() => {
try {
let x = onRejected(this.value);
resolvePromise(promise2, x, resolve, reject);
} catch (error) {
reject(error);
}
});
}
});
return promise2;
}
}
本文参考:https://juejin.cn/post/7043758954496655397
更详细、更完整代码(包含注释)可以参考以上连接