話不多說,直接上代碼
通過ES5的模塊化封裝,向外暴露一個屬性
(function(window){
const PENDING = 'pending';
const RESOLVED = 'fulfilled'
const REJECTED = 'rejected'
function MyPromise(excutor){
const self = this; //保存Promise對象,防止異步執行時,拿不到數據和方法,必要
self.value = undefined;
self.status = PENDING;
self.callbacks = [] //當狀態沒有發生改變時,需要儲存起回調函數, 在then方法中獲取回調函數
function resolve(value){
self.value = value;
self.status = RESOLVED;
self.callbacks.map(cb => {
setTimeout(() => { //定時器模擬異步執行,必須保證回調異步執行,否則順序就亂了
cb.onResolved(self.value)
})
}) //執行保存起來的成功回調函數
}
function reject(value){
self.value = value;
self.status = REJECTED ;
self.callbacks.map(cb => {
setTimeout(() => {
cb.onRejected (self.value)
})
})//執行保存起來的失敗的回調函數
}
try{ //若在執行器函數中主動拋出錯誤,需要捕獲錯誤,並把狀態更改為rejected
excutor(resolve,reject)
} catch (error){
reject(error)
}
}
MyPromise.prototype.then = function( onResolved,onRejected ){
const self = this//保存當前的Promise對象
return new Promise(resolve,reject){
onResolved = onResolved === 'function' ? onResolved : v => v
onRejected = onRejected === 'function' ? onRejected : error => {throw error} //實現異常透傳
//判斷當前的狀態
//假如Promise執行的異步任務,then方法是同步方法,那么當時Promise的狀態為pending,所以不能執行回調,此時需要保存
if(self.status === PENDING){
// 這里只是把回調保存了起來,並沒有改變當前的Promise對象,所以得進一步處理,處理和成功得處理類似
self.callbacks.push({onResolved,onRejected}) //保存每一個then方法為一個對象,包含onResolved,onRejected兩個函數
} else if(self.status === RESOLVED){
//1. 保證then中的回調異步執行,加一個setTimeout
//2. 在onResolved中如果主動拋出錯誤,需要捕獲錯誤
//3. 根據Promise對象返回的結果,來決定下一個then中執行成功還是失敗的回調
//4. 如果上一個Promise返回的是一個值,如return 2,那么直接用resolve(2)執行
//5. 如果上一個Promise返回的是一個promise對象,那么要通過promise.then 來獲取promise的執行結果
setTimeout(() => {
try {
const result = onResolved(self.value)
if( result instanceof MyPromise){ //判斷返回值是不是Promise對象
//返回一個Promise對象
result.then(
value => { //返回值是Promise對象,並且是成功的,那么就會執行這一個函數
resolve(self.value)
}
error => { //返回值是Promise對象,並且是失敗的,那么就會執行這一個函數
rejecte(self.value)
}
)
}else { //返回的不是一個Promise對象
resolve(self.value)
}
} catch (error) {
//與成功的處理一樣,只需要更改一下回調函數,太長就不寫了
}
})
} else { //rejected狀態}
}
}
window.MyPromise = MyPromise //向外暴露方法
})(window)
到這里就差不多寫完簡易的promise了,了解了原理也能更好的使用promise
歡迎指正,若有不清楚,也可評論指出
