new Promise((resolve, reject) => {
//异步成功执行resolve,否则执行reject
}).then((res) => {
//resolve触发第一个回调函数执行
}, (err) => {
//reject触发第二个回调函数执行
}).then(res => {
//需要保证then方法返回的依然是promise
//这样才能实现链式调用
}).catch(reason => {
//catch就相当于then
});
//等待所有的promise都成功执行then,
//反之只要有一个失败就会执行catch
Promise.all([promise1, ...]).then();
初步实现Promise:
1.实现三种状态:‘pending’, ‘fulfilled’, ‘rejected’
2.能够实现then方法两种回调函数的处理
//promise.js
class Promise{
constructor(excutorCallBack){
this.status = 'pending';
this.value = undefined;
this.fulfillAry = [];
this.rejectedAry = [];
//=>执行Excutor
let resolveFn = result => {
if(this.status !== 'pending') return;
let timer = setTimeout(() => {
this.status = 'fulfilled';
this.value = result;
this.fulfillAry.forEach(item => item(this.value));
}, 0);
};
let rejectFn = reason => {
if(this.status !== 'pending')return;
let timer = setTimeout(() => {
this.status = 'rejected';
this.value = reason;
this.rejectedAry.forEach(item => item(this.value))
})
};
try{
excutorCallBack(resolveFn, rejectFn);
} catch(err) {
//=>有异常信息按照rejected状态处理
rejectFn(err);
}
}
then(fulfilledCallBack, rejectedCallBack) {
this.fulfillAry.push(fulfilledCallBack);
this.rejectedAry.push(rejectedCallBack);
}
}
module.exports = Promise;
测试如下:
let Promise = require('./promise');
let p1 = new Promise((resolve, reject) => {
setTimeout(() => {
Math.random()<0.5?resolve(100):reject(-100);
}, 1000)
}).then(res => {
console.log(res);
}, err => {
console.log(err);
})
最大的难点在于链式调用的实现,具体来说就是then方法的实现。
then(fulfilledCallBack, rejectedCallBack) {
typeof fulfilledCallBack !== 'function' ? fulfilledCallBack = result => result:null;
typeof rejectedCallBack !== 'function' ? rejectedCallBack = reason => {
throw new Error(reason instanceof Error? reason.message:reason);
} : null
return new Promise((resolve, reject) => {
this.fulfillAry.push(() => {
try {
let x = fulfilledCallBack(this.value);
x instanceof Promise ? x.then(resolve, reject):resolve(x);
}catch(err){
reject(err)
}
});
this.rejectedAry.push(() => {
try {
let x = this.rejectedCallBack(this.value);
x instanceof Promise ? x.then(resolve, reject):resolve(x);
}catch(err){
reject(err)
}
})
}) ;
}
测试用例:
let p1 = new Promise((resolve, reject) => {
setTimeout(() => {
Math.random()<0.5?resolve(100):reject(-100);
}, 1000)
})
let p2 = p1.then(result => {
//执行then返回的是一个新的Promise
return result + 100;
})
let p3 = p2.then(result => {
console.log(result);
}, reason => {
console.log(reason)
})
简单画图来模拟一下链式调用的内部流程:
有了then方法,catch自然而然调用即可:
catch(rejectedCallBack) {
return this.then(null, rejectedCallBack);
}
接下来实现Promise.all()
//为类的静态方法,而不是在原型上
static all(promiseAry = []) {
let index = 0,
result = [];
return new Promise((resolve, reject) => {
for(let i = 0; i < promiseAry.length; i++){
promiseAry[i].then(val => {
index++;
result[i] = val;
if( index === promiseAry.length){
resolve(result)
}
}, reject);
}
})
}
现在手写一个简陋但是功能较为完备的Promise就大功告成了。
class Promise{
constructor(excutorCallBack){
this.status = 'pending';
this.value = undefined;
this.fulfillAry = [];
this.rejectedAry = [];
//=>执行Excutor
let resolveFn = result => {
if(this.status !== 'pending') return;
let timer = setTimeout(() => {
this.status = 'fulfilled';
this.value = result;
this.fulfillAry.forEach(item => item(this.value));
}, 0);
};
let rejectFn = reason => {
if(this.status !== 'pending')return;
let timer = setTimeout(() => {
this.status = 'rejected';
this.value = reason;
this.rejectedAry.forEach(item => item(this.value))
})
};
try{
excutorCallBack(resolveFn, rejectFn);
} catch(err) {
//=>有异常信息按照rejected状态处理
rejectFn(err);
}
}
then(fulfilledCallBack, rejectedCallBack) {
typeof fulfilledCallBack !== 'function' ? fulfilledCallBack = result => result:null;
typeof rejectedCallBack !== 'function' ? rejectedCallBack = reason => {
throw new Error(reason instanceof Error? reason.message:reason);
} : null
return new Promise((resolve, reject) => {
this.fulfillAry.push(() => {
try {
let x = fulfilledCallBack(this.value);
x instanceof Promise ? x.then(resolve, reject ):resolve(x);
}catch(err){
reject(err)
}
});
this.rejectedAry.push(() => {
try {
let x = this.rejectedCallBack(this.value);
x instanceof Promise ? x.then(resolve, reject):resolve(x);
}catch(err){
reject(err)
}
})
}) ;
}
catch(rejectedCallBack) {
return this.then(null, rejectedCallBack);
}
static all(promiseAry = []) {
let index = 0,
result = [];
return new Promise((resolve, reject) => {
for(let i = 0; i < promiseAry.length; i++){
promiseAry[i].then(val => {
index++;
result[i] = val;
if( index === promiseAry.length){
resolve(result)
}
}, reject);
}
})
}
}
module.exports = Promise;