new Promise((resolve, reject) => {
//異步成功執行resolve,不然執行reject
}).then((res) => {
//resolve觸發第一個回調函數執行
}, (err) => {
//reject觸發第二個回調函數執行
}).then(res => {
//須要保證then方法返回的依然是promise
//這樣才能實現鏈式調用
}).catch(reason => {
});
//等待全部的promise都成功執行then,
//反之只要有一個失敗就會執行catch
Promise.all([promise1, ...]).then();
複製代碼
初步實現Promise:promise
1.實現三種狀態:‘pending’, 'fulfilled', 'rejected'dom
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) {
//resolve和reject函數其實一個做爲微任務
//所以他們不是當即執行,而是等then調用完成後執行
this.fulfillAry.push(fulfilledCallBack);
this.rejectedAry.push(rejectedCallBack);
//一頓push事後他們被執行
}
}
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傳進兩個函數
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
//返回新的Promise對象,後面稱它爲「新Promise」
return new Promise((resolve, reject) => {
//注意這個this指向目前的Promise對象,而不是新的Promise
//再強調一遍,很重要:
//目前的Promise(不是這裏return的新Promise)的resolve和reject函數其實一個做爲微任務
//所以他們不是當即執行,而是等then調用完成後執行
this.fulfillAry.push(() => {
try {
//把then裏面的方法拿過來執行
//執行的目的已經達到
let x = fulfilledCallBack(this.value);
//下面執行以後的下一步,也就是記錄執行的狀態,決定新Promise如何表現
//若是返回值x是一個Promise對象,就執行then操做
//若是不是Promise,直接調用新Promise的resolve函數,
//新Promise的fulfilAry如今爲空,在新Promise的then操做後.新Promise的resolve執行
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)
}
})
}) ;
}
複製代碼
測試用例:ui
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)
})
複製代碼
簡單畫圖來模擬一下鏈式調用的內部流程: this
catch(rejectedCallBack) {
return this.then(null, rejectedCallBack);
}
複製代碼
接下來實現Promise.all()spa
//爲類的靜態方法,而不是在原型上
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);
}
})
}
複製代碼
接下來是race方法code
static race(promises) {
return new Promise((resolve, reject) => {
if (promises.length === 0) {
return;
} else {
for(let i = 0; i < promises.length; i++){
promises[i].then(val => {
resolve(result);
return;
}
}, reject);
}
}
});
}
複製代碼
static resolve (value) {
if (value instanceof Promise) return value
return new Promise(resolve => resolve(value))
}
複製代碼
static reject (value) {
return new Promise((resolve, reject) => reject(value))
}
複製代碼
如今手寫一個簡陋可是功能較爲完備的Promise就大功告成了。cdn
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);
}
})
}
static race(promiseAry) {
return new Promise((resolve, reject) => {
if (promiseAry.length === 0) {
return;
}
for (let i = 0; i < promiseAry.length; i++) {
promiseAry[i].then(val => {
resolve(val);
return;
}, reject);
}
})
}
static resolve (value) {
if (value instanceof Promise) return value
return new Promise(resolve => resolve(value))
}
static reject (value) {
return new Promise((resolve, reject) => reject(value))
}
}
module.exports = Promise;
複製代碼