注:
- 此文章仅为学习Promise的原理,有一些细节问题和边界处理没有判断,代码不可用于生产环境。如:浏览器内置的Promise使用微任务实现异步,这里用
setTimeout
宏任务实现异步。当Promise代码书写过程中嵌入setTimeout
代码的时候,输出可能与浏览器不一样。这里没有完全模拟浏览器的微任务 - 完整代码-github。其中每一个commit都对应一个小标题,可以对照查看
初始结构
使用:
let p = new Promise((resolve, reject) => {
resolve('OK');
});
p.then(value => {
console.log(value);
}, reason=>{
console.warn(reason);
})
复制代码
基本结构:
//声明构造函数
function Promise(executor){
}
//添加 then 方法
Promise.prototype.then = function(onResolved, onRejected){
}
复制代码
resolve
与 reject
结构
//声明构造函数
function Promise(executor){
//resolve 函数
function resolve(data){
}
//reject 函数
function reject(data){
}
//同步调用『执行器函数』
executor(resolve, reject);
}
//添加 then 方法
Promise.prototype.then = function(onResolved, onRejected){
}
复制代码
resolve
与 reject
函数实现
resolve
, reject
函数执行后,做了两件事
- 修改对象的状态(promiseState)
- 设置对象的结果值(promiseResult)
所以,实例需要两个属性,存储状态和结果。然后在 resolve
与 reject
函数中改变状态与结果值
function Promise(executor){
//添加属性
this.PromiseState = 'pending';
this.PromiseResult = null;
//保存实例对象的 this 的值
const self = this;// self _this that
//resolve 函数
function resolve(data){
//1. 修改对象的状态 (promiseState)
self.PromiseState = 'fulfilled';// resolved
//2. 设置对象结果值 (promiseResult)
self.PromiseResult = data;
}
//reject 函数
function reject(data){
//1. 修改对象的状态 (promiseState)
self.PromiseState = 'rejected';//
//2. 设置对象结果值 (promiseResult)
self.PromiseResult = data;
}
//同步调用『执行器函数』
executor(resolve, reject);
}
//添加 then 方法
Promise.prototype.then = function(onResolved, onRejected){
}
复制代码
throw
抛出错误改变状态
改变对象状态有三种方式:resolve
,reject
,抛出异常
这里我们完善一下抛出异常时改变状态的逻辑
如下try catch
方法:
//声明构造函数
function Promise(executor){
//添加属性
this.PromiseState = 'pending';
this.PromiseResult = null;
//保存实例对象的 this 的值
const self = this;// self _this that
//resolve 函数
function resolve(data){
//1. 修改对象的状态 (promiseState)
self.PromiseState = 'fulfilled';// resolved
//2. 设置对象结果值 (promiseResult)
self.PromiseResult = data;
}
//reject 函数
function reject(data){
//1. 修改对象的状态 (promiseState)
self.PromiseState = 'rejected';//
//2. 设置对象结果值 (promiseResult)
self.PromiseResult = data;
}
try{
//同步调用『执行器函数』
executor(resolve, reject);
}catch(e){
//修改 promise 对象状态为『失败』
reject(e);
}
}
//添加 then 方法
Promise.prototype.then = function(onResolved, onRejected){
}
复制代码
测试一下
let p = new Promise((resolve, reject) => {
// resolve('OK');
// reject("error");
//抛出异常
throw "error";
});
console.log(p);
复制代码
[[]]
双括号表示这两个属性是浏览器规定的内置属性,我们没有办法通过js去直接操作
以上就是基本的结构,接下来处理细节问题
状态只能修改一次
状态只能修改一次,只能从 pending
转为 fulfilled
或者 reject
思路:在改变状态之前,判断一下状态是否被改过了,如果被改过了就不再进行操作
//声明构造函数
function Promise(executor){
//添加属性
this.PromiseState = 'pending';
this.PromiseResult = null;
//保存实例对象的 this 的值
const self = this;// self _this that
//resolve 函数
function resolve(data){
//判断状态
if(self.PromiseState !== 'pending') return;
//1. 修改对象的状态 (promiseState)
self.PromiseState = 'fulfilled';// resolved
//2. 设置对象结果值 (promiseResult)
self.PromiseResult = data;
}
//reject 函数
function reject(data){
//判断状态
if(self.PromiseState !== 'pending') return;
//1. 修改对象的状态 (promiseState)
self.PromiseState = 'rejected';//
//2. 设置对象结果值 (promiseResult)
self.PromiseResult = data;
}
try{
//同步调用『执行器函数』
executor(resolve, reject);
}catch(e){
//修改 promise 对象状态为『失败』
reject(e);
}
}
//添加 then 方法
Promise.prototype.then = function(onResolved, onRejected){
}
复制代码
测试一下
let p = new Promise((resolve, reject) => {
reject("error");
resolve('OK');
});
console.log(p);
复制代码
then
方法执行回调
then
中的两个回调函数执行,有他自己的条件,如果状态为 fulfilled
,执行第一个,如果是 rejected
,就执行第二个
注意此时仅仅只能运行同步修改状态的回调
//添加 then 方法
Promise.prototype.then = function(onResolved, onRejected){
//调用回调函数 PromiseState
if(this.PromiseState === 'fulfilled'){
onResolved(this.PromiseResult);
}
if(this.PromiseState === 'rejected'){
onRejected(this.PromiseResult);
}
}
复制代码
测试一下,三种修改状态的方式,都可以正常运行
let p = new Promise((resolve, reject) => {
// resolve('OK');
// reject("Error");
throw "ERROR";
});
p.then(value => {
console.log(value);
}, reason=>{
console.warn(reason);
})
复制代码
异步任务 then
回调的执行
上面的代码仅仅支持同步代码,如果包裹一个异步操作,那么无法正常运行,例如下面:
let p = new Promise((resolve, reject) => {
setTimeout(() => {
resolve('OK');
// reject("error");
}, 1000);
});
p.then(value => {
console.log(value);
}, reason=>{
console.warn(reason);
});
console.log(p);
复制代码
没有任何输出,这里是因为,如果同步执行代码,遇到异步操作,那么同步执行的代码运行到 then
一直是 pending
状态。所以没有任何反应。那么我们修改一下整体和 then
的逻辑。
- 在Promise构造函数中,添加
callback
属性,存放执行异步操作时then
的回调函数 - 在
then
方法中判断,如果执行器executor
执行的是异步操作,那么状态应该为pending
,那么此时就把回调函数暂存起来 - 在异步到时间,执行
resolve
和reject
的时候,再将响应的callback
拿出来执行
代码如下:注意三个地方的callback
的处理
//声明构造函数
function Promise(executor){
//添加属性
this.PromiseState = 'pending';
this.PromiseResult = null;
//声明属性
this.callback = {};
//保存实例对象的 this 的值
const self = this;// self _this that
//resolve 函数
function resolve(data){
//判断状态
if(self.PromiseState !== 'pending') return;
//1. 修改对象的状态 (promiseState)
self.PromiseState = 'fulfilled';// resolved
//2. 设置对象结果值 (promiseResult)
self.PromiseResult = data;
//调用成功的回调函数
if(self.callback.onResolved){
self.callback.onResolved(data);
}
}
//reject 函数
function reject(data){
//判断状态
if(self.PromiseState !== 'pending') return;
//1. 修改对象的状态 (promiseState)
self.PromiseState = 'rejected';//
//2. 设置对象结果值 (promiseResult)
self.PromiseResult = data;
//执行回调
if(self.callback.onRejected){
self.callback.onRejected(data);
}
}
try{
//同步调用『执行器函数』
executor(resolve, reject);
}catch(e){
//修改 promise 对象状态为『失败』
reject(e);
}
}
//添加 then 方法
Promise.prototype.then = function(onResolved, onRejected){
//调用回调函数 PromiseState
if(this.PromiseState === 'fulfilled'){
onResolved(this.PromiseResult);
}
if(this.PromiseState === 'rejected'){
onRejected(this.PromiseResult);
}
//判断 pending 状态
if(this.PromiseState === 'pending'){
//保存回调函数
this.callback = {
onResolved,
onRejected
}
}
}
复制代码
再执行一下上面的异步测试操作:
正常
指定多个回调
let p = new Promise((resolve, reject) => {
setTimeout(() => {
// resolve('OK');
reject('No');
}, 1000);
});
p.then(value => {
console.log(value);
}, reason=>{
console.warn(reason);
});
p.then(value => {
alert(value);
}, reason=>{
alert(reason);
});
复制代码
如果像上面这样,仅仅会 alert
,并没有打印,原因很多简单,因为第二次执行 then
,会把第一次存的 callback
覆盖,所以只有最后一次 then
有效。
所以我们用一种新的方法来解决这个问题,当遇到 then
的时候,将两个回调函数存到一个数组里,等到异步 resolve
的时候,从数组中拿出存的回调,依次执行
代码修改如下:
- 将
callback
声明为一个数组 resolve
或者reject
的时候,从数组总拿出回调函数执行then
的时候,将回调函数存在callback
数组中
//声明构造函数
function Promise(executor){
//添加属性
this.PromiseState = 'pending';
this.PromiseResult = null;
//声明属性
this.callbacks = [];
//保存实例对象的 this 的值
const self = this;// self _this that
//resolve 函数
function resolve(data){
//判断状态
if(self.PromiseState !== 'pending') return;
//1. 修改对象的状态 (promiseState)
self.PromiseState = 'fulfilled';// resolved
//2. 设置对象结果值 (promiseResult)
self.PromiseResult = data;
//调用成功的回调函数
self.callbacks.forEach(item => {
item.onResolved(data);
});
}
//reject 函数
function reject(data){
//判断状态
if(self.PromiseState !== 'pending') return;
//1. 修改对象的状态 (promiseState)
self.PromiseState = 'rejected';//
//2. 设置对象结果值 (promiseResult)
self.PromiseResult = data;
//执行失败的回调
self.callbacks.forEach(item => {
item.onRejected(data);
});
}
try{
//同步调用『执行器函数』
executor(resolve, reject);
}catch(e){
//修改 promise 对象状态为『失败』
reject(e);
}
}
//添加 then 方法
Promise.prototype.then = function(onResolved, onRejected){
//调用回调函数 PromiseState
if(this.PromiseState === 'fulfilled'){
onResolved(this.PromiseResult);
}
if(this.PromiseState === 'rejected'){
onRejected(this.PromiseResult);
}
//判断 pending 状态
if(this.PromiseState === 'pending'){
//保存回调函数
this.callbacks.push({
onResolved: onResolved,
onRejected: onRejected
});
}
}
复制代码
同步修改状态 then
方法返回结果(then链的实现)
then
方法返回结果有以下规则:
then
方法返回结果是由他指定的回调函数的返回结果决定的
- 如果返回一个非Promise类型的数据,
then
方法返回的就是一个成功状态的Promise,返回值就是return的值 - 如果返回了一个Promise类型的数据,
then
方法返回的的结果和状态就由返回的这个Promise决定 - 如果抛出错误,就返回一个失败的Promise,值为错误
测试代码:
//实例化对象
let p = new Promise((resolve, reject) => {
resolve('OK');
});
//执行 then 方法
const res = p.then(value => {
console.log(value)
//抛出异常测试
//throw "FAIL";
}, reason=>{
console.warn(reason);
});
console.log(res);
复制代码
下面实现这个流程
//添加 then 方法
Promise.prototype.then = function(onResolved, onRejected){
//1. 返回的是Promise类型的数据
return new Promise((resolve, reject) => {
//调用回调函数 PromiseState
if(this.PromiseState === 'fulfilled'){
try{4. 处理抛出异常的情况
//2. 获取回调函数的执行结果
let result = onResolved(this.PromiseResult);
//3. 判断
if(result instanceof Promise){
//3.1如果是 Promise 类型的对象
//返回的结果就是返回的这个Promise(result)的值和状态
//返回的Promise的值和状态(result)又由这个result的then来决定,then中的回调代表最后这个Promise到底是什么状态.
result.then(v => {
resolve(v);
}, r=>{
reject(r);
})
}else{
//3.2如果不是Promise类型
//结果的对象状态为『成功』,值就是then回调函数执行的结果
resolve(result);
}
}catch(e){
reject(e);
}
}
if(this.PromiseState === 'rejected'){
try{
let result = onRejected(this.PromiseResult);
if(result instanceof Promise){
result.then(v => {
resolve(v);
}, r=>{
reject(r);
})
}else{
resolve(result);
}
}catch(e){
reject(e);
}
}
//判断 pending 状态
if(this.PromiseState === 'pending'){
//保存回调函数
this.callbacks.push({
onResolved: onResolved,
onRejected: onRejected
});
}
})
}
复制代码
可以看上面1,2,3三个步骤
- 首先
then
返回的是Promise
类型的数据,所以return new Promise
- 首先获取
then
回调函数的执行结果result
- 看
result
是什么值- 3.1 如果
result
是Promise
。那么最后then
返回的结果就由result的结果来决定。而result
的结果和值是通过.then
来获知的,所以获取结果后,再返回给最外面的Promise - 3.2 如果不是
Promise
类型,那么回调函数的结果,就是结果
- 3.1 如果
- 注意不要忘记处理抛出异常的情况
同样,当状态为 rejected
的时候执行一样的逻辑
接下来测试一下几种 then
链的情况
let p = new Promise((resolve, reject) => {
resolve('OK');
});
//执行 then 方法
const res = p.then(value => {
console.log(value)
return 'okokok'
}, reason=>{
console.warn(reason);
});
console.log(res);
复制代码
let p = new Promise((resolve, reject) => {
resolve('OK');
});
//执行 then 方法
const res = p.then(value => {
console.log()
return new Promise((resolve,reject)=>{
resolve('r test')
})
}, reason=>{
console.warn(reason);
});
console.log(res);
复制代码
let p = new Promise((resolve, reject) => {
resolve('OK');
});
//执行 then 方法
const res = p.then(value => {
//抛出异常
throw "FAIL";
}, reason=>{
console.warn(reason);
});
console.log(res);
复制代码
在异步状态下修改 then
方法的返回结果(异步执行时的 then
链)
上面then
链的实现仅仅只能在Promise同步修改状态时可用。下面实现在异步操作下修改 then
方法的返回结果。
当出现异步操作时,进入 then
函数的时候,Promise处于 pending
状态,所以在 pending
的时候,存储回调函数时,也要进行同样的 then
链的处理。
因为对then链的处理都是一样的逻辑,仅仅是执行的函数不同,所以可以将逻辑抽离出来,封装为一个函数。进行代码的优化
最后还要注意 this
的指向问题
//添加 then 方法
Promise.prototype.then = function(onResolved, onRejected){
//1. 注意this指向问题
const self = this;
return new Promise((resolve, reject) => {
//2. 封装函数,then链的处理机制
function callback(type){
try{
//获取回调函数的执行结果
let result = type(self.PromiseResult);
//判断
if(result instanceof Promise){
//如果是 Promise 类型的对象
result.then(v => {
resolve(v);
}, r=>{
reject(r);
})
}else{
//结果的对象状态为『成功』
resolve(result);
}
}catch(e){
reject(e);
}
}
//调用回调函数 PromiseState
//3. 不同的状态进行不同的then链处理
if(this.PromiseState === 'fulfilled'){
callback(onResolved);
}
if(this.PromiseState === 'rejected'){
callback(onRejected);
}
//判断 pending 状态
if(this.PromiseState === 'pending'){
//保存回调函数
this.callbacks.push({
onResolved: function(){
callback(onResolved);
},
onRejected: function(){
callback(onRejected);
}
});
}
})
}
复制代码
几个修改的地方如下:
- 注意
this
的指向问题,type(self.PromiseResult)
传入的状态是原来的Promise的状态 - 封装函数,传入需要执行的函数
- 不同状态下进行不同的
then
链的处理
测试一下不同的情况,注意1s之后在查看打印,因为1s之后回调才执行完毕:
let p = new Promise((resolve, reject) => {
setTimeout(() => {
resolve('ok');
// reject('Error');
}, 1000);
});
//执行 then 方法
const res = p.then(value => {
console.log(value);
return value
}, reason=>{
console.warn(reason);
});
console.log(res);
复制代码
let p = new Promise((resolve, reject) => {
setTimeout(() => {
resolve('ok');
// reject('Error');
}, 1000);
});
//执行 then 方法
const res = p.then(value => {
console.log(value);
return new Promise((resolve, reject) => {
resolve('new p')
})
}, reason=>{
console.warn(reason);
});
console.log(res);
复制代码
let p = new Promise((resolve, reject) => {
setTimeout(() => {
resolve('ok');
// reject('Error');
}, 1000);
});
//执行 then 方法
const res = p.then(value => {
console.log(value);
throw 'errerr'
}, reason=>{
console.warn(reason);
});
console.log(res);
复制代码
reject
状态也是一样,不再进行测试
catch
方法
catch
是 then
的语法糖,所以
//添加 catch 方法
Promise.prototype.catch = function(onRejected){
return this.then(undefined, onRejected);
}
复制代码
then
链穿透
then
链的穿透机制如下,如果不传 then
的回调函数,(或者回调函数不是函数类型)那么处理将会继续延伸到下一个 then
看一下我们刚才的代码,当传入一个 undefined
的时候,无法运行,那么将会报错
所以我们判断then
传入的值即可
异常穿透
完善异常穿透机制:
Promise.prototype.then = function(onResolved, onRejected){
const self = this;
//判断回调函数参数
if(typeof onRejected !== 'function'){
onRejected = reason => {
throw reason;
}
}
...//剩余代码先不写
}
复制代码
测试:
let p = new Promise((resolve, reject) => {
setTimeout(() => {
reject('OK');
// resolve('OK');
}, 1000);
});
//异常穿透
p.then()
.then(value=>{
console.log(222);
}).then(value => {
console.log(333);
}).catch(reason => {
console.warn(reason);
});
复制代码
或者中途出现错误
let p = new Promise((resolve, reject) => {
setTimeout(() => {
// reject('OK');
resolve('OK');
}, 1000);
});
//异常穿透
p.then()
.then(value=>{
throw 'ok1'
console.log(222);
}).then(value => {
console.log(333);
}).catch(reason => {
console.warn(reason);
});
复制代码
值传递
延伸一下,不光错误可以传递,成功的回调也可以传递。如果第一个回调函数不传,会把值继续传到下一个 then
中的第一个回调处理。实现也很简单,直接将 onResolve
函数改为传入什么,返回什么的函数即可
Promise.prototype.then = function(onResolved, onRejected){
const self = this;
//判断回调函数参数
if(typeof onRejected !== 'function'){
onRejected = reason => {
throw reason;
}
}
if(typeof onResolved !== 'function'){
onResolved = value => value;
}
}
复制代码
then
方法回调的异步执行
这里有一个细节, then
方法中的回调函数是异步执行的
then
方法的回调在内置的Promise中是异步执行的微任务,等所有同步代码执行完毕后,才会执行then中的异步微任务回调。这里我们用 setTimeout
来模拟实现
由于原生的 Promise 是V8引擎提供的微任务,我们无法还原V8引擎的实现,所以这里使用 setTimeout 模拟异步,所以原生的是微任务,这里是宏任务。
Promise A+ 规范3.1 中也提到了:这可以通过“宏任务”机制(例如setTimeout或setImmediate)或“微任务”机制(例如MutatonObserver或)来实现process。nextTick。
如果想实现 promise 的微任务,可以 mutationObserver 替代 seiTimeout 来实现微任务。
有小伙伴说可以使用 queueMicrotask 实现微任务,我也查阅了一些资料,是可以的。不过 queueMicrotask 兼容性不是很好,IE 下完全不支持。据我所知 queueMicrotask 的 polyfill 是基于 promise 实现的,如果不支持 promise 会转成 setTimeout。
总的来说,queueMicrotask 和 mutationObserver 都可以实现微任务机制,不过更建议有执念的小伙伴用 mutationObserver 实现一下,没有执念的小伙伴了解 promise 的微任务机制就好了~
如下面的代码输出
let p1 = new Promise((resolve, reject) => {
reject('OK');
console.log(111);
});
p1.then(value => {
console.log(222);
}, reason => {
console.log(444);
});
console.log(333);
复制代码
我们来测试一下如果不进行异步回调操作,用我们自己写的代码测试一下输出:
直接按照顺序输出
但是如果是浏览器原生的Promise输出,结果应该为:
所以then
中的回调应该是异步的,所以要在执行回调的时候,加上 setTimeout
。
以下是Promise的完整的代码(注意加上 setTimeout
的部分:
//声明构造函数
function Promise(executor){
//添加属性
this.PromiseState = 'pending';
this.PromiseResult = null;
//声明属性
this.callbacks = [];
//保存实例对象的 this 的值
const self = this;// self _this that
//resolve 函数
function resolve(data){
//判断状态
if(self.PromiseState !== 'pending') return;
//1. 修改对象的状态 (promiseState)
self.PromiseState = 'fulfilled';// resolved
//2. 设置对象结果值 (promiseResult)
self.PromiseResult = data;
//调用成功的回调函数
setTimeout(() => {
self.callbacks.forEach(item => {
item.onResolved(data);
});
});
}
//reject 函数
function reject(data){
//判断状态
if(self.PromiseState !== 'pending') return;
//1. 修改对象的状态 (promiseState)
self.PromiseState = 'rejected';//
//2. 设置对象结果值 (promiseResult)
self.PromiseResult = data;
//执行失败的回调
setTimeout(() => {
self.callbacks.forEach(item => {
item.onRejected(data);
});
});
}
try{
//同步调用『执行器函数』
executor(resolve, reject);
}catch(e){
//修改 promise 对象状态为『失败』
reject(e);
}
}
//添加 then 方法
Promise.prototype.then = function(onResolved, onRejected){
const self = this;
//判断回调函数参数
if(typeof onRejected !== 'function'){
onRejected = reason => {
throw reason;
}
}
if(typeof onResolved !== 'function'){
onResolved = value => value;
//value => { return value};
}
return new Promise((resolve, reject) => {
//封装函数
function callback(type){
try{
//获取回调函数的执行结果
let result = type(self.PromiseResult);
//判断
if(result instanceof Promise){
//如果是 Promise 类型的对象
result.then(v => {
resolve(v);
}, r=>{
reject(r);
})
}else{
//结果的对象状态为『成功』
resolve(result);
}
}catch(e){
reject(e);
}
}
//调用回调函数 PromiseState
if(this.PromiseState === 'fulfilled'){
setTimeout(() => {
callback(onResolved);
});
}
if(this.PromiseState === 'rejected'){
setTimeout(() => {
callback(onRejected);
});
}
//判断 pending 状态
if(this.PromiseState === 'pending'){
//保存回调函数
this.callbacks.push({
onResolved: function(){
callback(onResolved);
},
onRejected: function(){
callback(onRejected);
}
});
}
})
}
//添加 catch 方法
Promise.prototype.catch = function(onRejected){
return this.then(undefined, onRejected);
}
复制代码
其他方法
Promise.resolve
//添加 resolve 方法
Promise.resolve = function(value){
//返回promise对象
return new Promise((resolve, reject) => {
if(value instanceof Promise){
value.then(v=>{
resolve(v);
}, r=>{
reject(r);
})
}else{
//状态设置为成功
resolve(value);
}
});
}
复制代码
Promise.reject
//添加 reject 方法
Promise.reject = function(reason){
return new Promise((resolve, reject)=>{
reject(reason);
});
}
复制代码
Promise.all
//添加 all 方法
Promise.all = function(promises){
//返回结果为promise对象
return new Promise((resolve, reject) => {
//声明变量
let count = 0;
let arr = [];
//遍历
for(let i=0;i<promises.length;i++){
//
promises[i].then(v => {
//得知对象的状态是成功
//每个promise对象 都成功
count++;
//将当前promise对象成功的结果 存入到数组中
arr[i] = v;
//判断
if(count === promises.length){
//修改状态
resolve(arr);
}
}, r => {
reject(r);
});
}
});
}
复制代码
Promise.race
//添加 race 方法
Promise.race = function(promises){
return new Promise((resolve, reject) => {
for(let i=0;i<promises.length;i++){
promises[i].then(v => {
//修改返回对象的状态为 『成功』
resolve(v);
},r=>{
//修改返回对象的状态为 『失败』
reject(r);
})
}
});
}
复制代码
class版本封装
以上代码为构造函数版本,用最新的class封装如下:
class Promise{
//构造方法
constructor(executor){
//添加属性
this.PromiseState = 'pending';
this.PromiseResult = null;
//声明属性
this.callbacks = [];
//保存实例对象的 this 的值
const self = this;// self _this that
//resolve 函数
function resolve(data){
//判断状态
if(self.PromiseState !== 'pending') return;
//1. 修改对象的状态 (promiseState)
self.PromiseState = 'fulfilled';// resolved
//2. 设置对象结果值 (promiseResult)
self.PromiseResult = data;
//调用成功的回调函数
setTimeout(() => {
self.callbacks.forEach(item => {
item.onResolved(data);
});
});
}
//reject 函数
function reject(data){
//判断状态
if(self.PromiseState !== 'pending') return;
//1. 修改对象的状态 (promiseState)
self.PromiseState = 'rejected';//
//2. 设置对象结果值 (promiseResult)
self.PromiseResult = data;
//执行失败的回调
setTimeout(() => {
self.callbacks.forEach(item => {
item.onRejected(data);
});
});
}
try{
//同步调用『执行器函数』
executor(resolve, reject);
}catch(e){
//修改 promise 对象状态为『失败』
reject(e);
}
}
//then 方法封装
then(onResolved,onRejected){
const self = this;
//判断回调函数参数
if(typeof onRejected !== 'function'){
onRejected = reason => {
throw reason;
}
}
if(typeof onResolved !== 'function'){
onResolved = value => value;
//value => { return value};
}
return new Promise((resolve, reject) => {
//封装函数
function callback(type){
try{
//获取回调函数的执行结果
let result = type(self.PromiseResult);
//判断
if(result instanceof Promise){
//如果是 Promise 类型的对象
result.then(v => {
resolve(v);
}, r=>{
reject(r);
})
}else{
//结果的对象状态为『成功』
resolve(result);
}
}catch(e){
reject(e);
}
}
//调用回调函数 PromiseState
if(this.PromiseState === 'fulfilled'){
setTimeout(() => {
callback(onResolved);
});
}
if(this.PromiseState === 'rejected'){
setTimeout(() => {
callback(onRejected);
});
}
//判断 pending 状态
if(this.PromiseState === 'pending'){
//保存回调函数
this.callbacks.push({
onResolved: function(){
callback(onResolved);
},
onRejected: function(){
callback(onRejected);
}
});
}
})
}
//catch 方法
catch(onRejected){
return this.then(undefined, onRejected);
}
//添加 resolve 方法
static resolve(value){
//返回promise对象
return new Promise((resolve, reject) => {
if(value instanceof Promise){
value.then(v=>{
resolve(v);
}, r=>{
reject(r);
})
}else{
//状态设置为成功
resolve(value);
}
});
}
//添加 reject 方法
static reject(reason){
return new Promise((resolve, reject)=>{
reject(reason);
});
}
//添加 all 方法
static all(promises){
//返回结果为promise对象
return new Promise((resolve, reject) => {
//声明变量
let count = 0;
let arr = [];
//遍历
for(let i=0;i<promises.length;i++){
//
promises[i].then(v => {
//得知对象的状态是成功
//每个promise对象 都成功
count++;
//将当前promise对象成功的结果 存入到数组中
arr[i] = v;
//判断
if(count === promises.length){
//修改状态
resolve(arr);
}
}, r => {
reject(r);
});
}
});
}
//添加 race 方法
static race (promises){
return new Promise((resolve, reject) => {
for(let i=0;i<promises.length;i++){
promises[i].then(v => {
//修改返回对象的状态为 『成功』
resolve(v);
},r=>{
//修改返回对象的状态为 『失败』
reject(r);
})
}
});
}
}
复制代码