在上一篇 Promise的介绍中,已经把PromiseA+的规范实现了一遍,今天把非规范中的辅助方法实现一遍,自己做个记录,方便以后查找
一共要实现这么几个
静态方法
- resolve
- race
- all
- race
原型方法
- catch
- finally
静态方法
resolve
在 resolve 可以传入普通属性和一个 promise类型,如果传递了promise,则会使用传递 promise 的状态
Promise.resolve(10).then(res=>{
console.log(res) // 10
})
Promise.resolve(new Promise((resolve,reject)=>{
resolve(100)
})).then(res=>{
console.log(res) // 100
})
在Promise.resolve 中还可以继续调用 then 链,所以要返回一个新的promise
所以我们可以写出这样的代码
class Promise {
constructor(executor) {
const onFulfilled = val => {
if (this.status == PENGING) {
if (val instanceof Promise) {
return val.then(onFulfilled, onRejected);
}
// ....
}
};
executor(onFulfilled);
}
static resolve(val) {
return new Promise((resolve, rejcet) => {
resolve(val);
});
}
}
reject
reject 也是同样的步骤,只不过,reject 不需要深度递归,因为外层 reject了,内部的Promise成功失败与否不重要了
static reject(err) {
return new Promise((resolve, rejcet) => {
rejcet(err);
});
}
all
all 方法必须所有的状态都是成功,才可以成功,只要有一个失败状态,就会走入失败 先看用法
Promise.all([Promise.resolve(10),2,3]).then(res=>{
console.log(res) // [10,2,3]
},err=>{
console.log(err)
})
all 方法可以接受普通值,也可以接收一个 promise 类型,并且返回一个按照传入顺序的结果数组
由于 all 也可以调用 then 链,所以也需要返回一个 新的 promise
static all(arr) {
if(arr.length == 0){
return Promise.resolve([])
}
return new Promise((resolve, rejcet) => {
let len = arr.length,
ret = [];
arr.forEach((val, idx) => {
Promise.resolve(val).then(res => {
ret[idx] = res;
if (--len == 0) {
resolve(ret);
}
}, rejcet);
});
});
}
race
比较两个 promise 的速度,哪个先快执行哪个
Promise.race([2,3,1]).then(res=>{
console.log(res) // 2
})
同样的,依然需要返回一个 新的 promise
static race(arr) {
return new Promise((resolve, reject) => {
arr.forEach(val => {
Promise.resolve(val).then(resolve, reject);
});
});
}
所以,all 传入一个 空数组,可以在 then 中返回一个空数组,race 传入一个空数组,不会有任何反应
举个 race 例子,如果一个请求超过 2s 以后自动取消,可以使用 rece 来比较请求的promise和自定义promise更改状态的时间
let p1 = new Promise(resolve => {
// 模拟请求
setTimeout(() => {
resolve(10);
}, 1000);
});
function withRabort(userPromise) {
let p,abort;
const innerPromise = new Promise((resolve, reject) => {
abort = reject;
});
p = Promise.race([userPromise, innerPromise]);
p.abort = abort
return p;
}
let p = withRabort(p1)
setTimeout(()=>{
p.abort("失败")
},2000)
原型方法
catch
Promise.reject(100).catch(res=>{
console.log(res)
})
比较简单
catch(callback) {
this.then(null, callback);
}
finally
不论成功或者失败都会执行
let p = new Promise((resolve)=>{
resolve(10)
})
p.then(res=>res).finally(res=>{
console.log(res,"finally") // undefined finally
})
在 finally 中是无法获得传递的 参数的,如果想获取,可以在callback()改为callback(value)
finally(callback) {
// value
return this.then(
value => this.resolve(callback()).then(() => value),
reason =>
this.resolve(callback()).then(() => {
throw reason;
})
);
}