上一篇文章根据Promise A+规范实现Promise,但是规范的Promise和ES6的Promise相比,还缺少部分功能,我们来依次实现他们。
Prmoise A+规范的Promise
const PENDING = 'pending';
const RESOLVED = 'resolved';
const REJECTED = 'rejected';
function resolvePromise(promise2, x, resolve, reject) {
if (promise2 === x) {
reject(new TypeError('Chaining cycle detected for promise #<Promise>'));
}
let called;
if ((typeof x === 'object' && x != null) || typeof x === 'function') {
try {
const then = x.then;
if (typeof then === 'function') {
then.call(
x,
y => {
if (called) return;
called = true;
resolvePromise(promise2, y, resolve, reject);
},
e => {
if (called) return;
called = true;
reject(e);
}
);
} else {
resolve(x);
}
} catch (e) {
if (called) return;
called = true;
reject(e);
}
} else {
resolve(x);
}
}
class Promise {
constructor(executor) {
this.status = PENDING;
this.value = undefined;
this.reason = undefined;
this.onResolvedCallbacks = [];
this.onRejectedCallbacks = [];
const resolve = value => {
if (value instanceof Promise) {
// 如果value是个Promise,递归解析,直到value为普通值
value.then(resolve, reject);
}
if (this.status === PENDING) {
this.status = RESOLVED;
this.value = value;
this.onResolvedCallbacks.forEach(fn => fn());
}
};
const reject = reason => {
if (this.status === PENDING) {
this.status = REJECTED;
this.reason = reason;
this.onRejectedCallbacks.forEach(fn => fn());
}
};
try {
executor(resolve, reject);
} catch (err) {
reject(err);
}
}
then(onFulfilled, onRejected) {
onFulfilled = typeof onFulfilled === 'function' ? onFulfilled : value => value;
onRejected = typeof onRejected === 'function' ? onRejected : err => throw err;
const promise2 = new Promise((resolve, reject) => {
if (this.status === RESOLVED) {
setTimeout(() => {
try {
const x = onFulfilled(this.value);
resolvePromise(promise2, x, resolve, reject);
} catch (e) {
reject(e);
}
}, 0);
}
if (this.status === REJECTED) {
try {
const x = onRejected(this.reason);
resolvePromise(promise2, x, resolve, reject);
} catch (e) {
reject(e);
}
}
if (this.status === PENDING) {
this.onResolvedCallbacks.push(() => {
try {
const x = onFulfilled(this.value);
resolvePromise(promise2, x, resolve, reject);
} catch (e) {
reject(e);
}
});
this.onRejectedCallbacks.push(() => {
try {
const x = onRejected(this.reason);
resolvePromise(promise2, x, resolve, reject);
} catch (e) {
reject(e);
}
});
}
});
return promise2;
}
}
// promise的延迟对象
Promise.defer = Promise.deferred = function () {
let dfd = {};
dfd.promise = new Promise((resolve,reject)=>{
dfd.resolve = resolve;
dfd.reject = reject;
})
return dfd
}
module.export = Promise;
catch方法
catch相当于then方法的变种
catch(errCallback) {
return this.then(null, errCallback);
}
Promise静态方法
- Promise.resolve(),快速创建一个成功的Promise;
- Promise.reject(),快速创建一个失败的Promise。
class Promise {
static resolve(value) {
return new Promise(resolve=> {
resolve(value);
})
}
static reject(reason) {
return new Promise(reject=> {
reject(reason);
})
}
}
finally()方法
- finally方法用于指定不管Promise对象最后状态如何都会执行的操作。它只接受一个普通的回调函数作为参数,该函数不管怎样都必须执行。它并不是表示最终的意思,也不会影响其他逻辑。
Promise.resolve('100').finally(
()=>{
console.log('finally');
}
).then(
res=> {
console.log(res);
}
)
// 或
Promise.reject('200')
.finally(
()=>{
console.log('finally');
}
).catch(
err=> {
console.log(err);
}
)
- 但是如果返回的是一个Promise,要等待finally中的Promise执行完以后,才会走下一个,如果这个Promise是失败态,那么会把finally中reject的结果传给失败的回调。
// 成功态
Promise.resolve('100')
.finally(
()=> {
return new Promise(resolve=> {
setTimeout(()=>{
resolve('success')
}, 3000)
})
}
)
.then(
res=> {
console.log(res); // 等待3秒后打印 100;
}
)
// 失败态
Promise.resolve('100')
.finally(
()=> {
return new Promise((resolve,reject)=> {
setTimeout(()=> {
reject('failed')
}, 3000)
})
}
)
.catch(
err=> {
console.log(err); // 等待3秒后打印 failed;
}
)
知道了finally的用法,那我们就来实现它
class Promise {
finally(callback) {
return this.then(
// finally前面是成功,就执行成功的回调,并把前面的参数向下传递
value=> {
// callback()执行完可能返回一个Promise
// 也可能不返回一个Promise,为了兼容,嵌套一层Promise.resolve保证向下传递
return Promise.resolve(callback()).then(()=> value)
}
// finally前面是失败,就执行失败的回调,并把前面的参数向下传递
reason=> {
return Promise.resolve(callback()).then(()=> throw reason)
}
)
}
}
Promise.all()
如果有三个请求同时执行,其中一个请求失败,另外两个请求依旧会执行,promise不会中断,只是最终不会采纳另外两个请求的结果。
const isPromise = value => typeof value.then === 'function';
Promise.all = function(promises) { // 全部成功才成功
return new Promise((resolve, reject) => {
// 异步 :并发 (使用for循环迭代执行) 和 串行(借助回调 第一个完成后调用第二个)
// 遍历数组 依次拿到执行结果
let arr = [];
let index = 0;
const processData = (key, data) => {
arr[key] = data; // 不能使用数组的长度来计算
if(++index === promises.length){
resolve(arr);
}
}
for (let i = 0; i < promises.length; i++) {
let result = promises[i];
if (isPromise(result)) {
result.then(
data => {
processData(i, data)
},
reject
)
} else {
processData(i, result)
}
}
});
}
Promise.race()
谁跑的快,用谁的,但是其他的也会执行,只是只采用最快的那个。
const isPromise = value => typeof value.then === 'function';
Promise.race = function(promises) {
return new Promise((resolve, reject) => {
for (let i = 0; i < promises.length; i++) {
let result = promises[i];
if(isPromise(result)){
result.then(resolve,reject)
}else{
resolve(result);
}
}
});
}
使用Promise.race()“中断”Promise
使用快的Promise,“中断”慢的Promise,其实也不是中断,只是不采纳慢的Promise的结果
比如有个请求要10s返回,结果,我等不及了,2秒后我就要“中断”他
const promise1 = new Promise((resolve, reject)=> {
setTimeout(()=> {
resolve('OK 成功了');
}, 10000)
})
// 把上面的promise1传入到wrap函数的race中
const wrap = promise=> {
let abort;
const p1 = new Promise((resolve, reject)=> {
abort = reject;
})
// 思路:提前reject p1,那么race采纳的就是p1的结果
const p2 = Promise.race([promise, p1]);
p2.abort = abort;
return p2;
}
const wrapPromise = wrap(promise1);
wrapPromise.then(
data=> {
console.log('success', data)
},
err=> {
console.log('failed', err); // failed 超时!
}
)
console.log(wrapPromise);
setTimeout(()=> {
wrapPromise.abort('超时!');
}, 2000)