網(wǎng)絡(luò)上面已經(jīng)有很多Promise的教程了。推薦一下這篇文章
但是本文的目的是為了使用最少量的代碼,以達(dá)到對(duì)Promise的實(shí)現(xiàn)有一個(gè)初步的了解。
下面是關(guān)于代碼實(shí)現(xiàn)的一些說明
- 代碼中暫時(shí)不考慮任何異常情況
- Promise對(duì)象只支持成功的回調(diào)
- Promise支持鏈?zhǔn)秸{(diào)用
- 本文僅實(shí)現(xiàn)兩種狀態(tài) 'pending' 和 'resolved'
第一步 定義Promise的內(nèi)部變量
self.status = 'pending';//初始狀態(tài)
self.onResolvedCallback = [];
self.data = undefined;
- status: 保存當(dāng)前Promise的狀態(tài), 初始化時(shí)為 pending 狀態(tài)
- onResolvedCallback: 當(dāng)Promise還處于pending狀態(tài)時(shí),將鏈?zhǔn)秸{(diào)用中的回調(diào)函數(shù)綁定到數(shù)組中
- data: 保存當(dāng)前Promise的返回值
第二步 定義resolve函數(shù)
function resolve(data){
if(self.status == 'pending'){
self.status = 'resolved';
self.data = data;
self.onResolvedCallback.forEach(callback => callback(data));
}
}
resolve 函數(shù)向外提供了修改當(dāng)前Promise狀態(tài)值的方法。并且保存Promise的結(jié)果。(如果在Promise 為 pending狀態(tài)時(shí),有鏈?zhǔn)交卣{(diào)。那么執(zhí)行這些回調(diào)函數(shù))
第三步 定義then方法
Promise.prototype.then = function(onResolved){
var self = this;
if(self.status == 'pending'){
return new Promise(function(resolve){
self.onResolvedCallback.push(function(value){
var result = onResolved(value);
resolve(result);
});
});
}else{//本文只實(shí)現(xiàn)了'pending' 和 'resolved'兩種狀態(tài),所以沒判斷rejected相關(guān)代碼
return new Promise(function(resolve){
var result = onResolved(self.data);
resolve(result);
});
}
}
then方法主要實(shí)現(xiàn)了兩步
- 當(dāng)Promise處于pending狀態(tài),保存回調(diào)函數(shù)到onResolvedCallback中,返回新的Promise實(shí)例
- 當(dāng)Promise不處于pending狀態(tài)時(shí),直接獲取上一步的返回值(self.data),調(diào)用回調(diào)函數(shù),返回新的Promise實(shí)例
以下為完整的代碼
function Promise(executor){
var self = this;
self.status = 'pending';
self.onResolvedCallback = [];
self.data = undefined;
function resolve(data){
if(self.status == 'pending'){
self.status = 'resolved';
self.data = data;
self.onResolvedCallback.forEach(callback => callback(data));
}
}
executor(resolve);//執(zhí)行回調(diào)函數(shù)
}
Promise.prototype.then = function(onResolved){
var self = this;
if(self.status == 'pending'){
return new Promise(function(resolve){
self.onResolvedCallback.push(function(value){
var result = onResolved(value);
resolve(result);
});
});
}else{
return new Promise(function(resolve){
var result = onResolved(self.data);
resolve(result);
});
}
}
以下為一個(gè)用例
new Promise(function(resolve){
setTimeout(function(){
resolve('123');
}, 3000);
}).then(function(value){
console.log('then 1', value);
return value + 1;
}).then(function(value2){
console.log('then 2', value);
return value2;
})
//等待3秒后,頁面上輸出
//then 1: 123
//then 2: 1231