包含promise原型對象的方法:.then() 和 .catch();
promise對象上的方法: resolve() / reject() / all() / race() ;
自定義promise對象方法:
Promise.resolvedDelay(value, time) 規定時間成功
Promise.rejectedDalay(reason, time ) 規定時間失敗
/*
自定義Promise函數模塊: IIFE
*/
(function (window) {
const PENDING = 'pending';
const RESOLVED = 'resolved';
const REJECTED = 'rejected';
/**
* Promise構造函數
* excutor: 執行器函數(同步執行)
*/
function Promise(excutor) {
// 將當前promise對象保存起來
const that = this;
that.status = PENDING; // 給promise對象指定status屬性,初始值為PENDING
that.data = undefined; // 給promise對象指定一個用于存出結果數據的屬性
that.callbacks = []; // 每個元素的結構: { onResolved() {}, onRejected() {} }
function resolve(value) {
// 如果當前狀態不是PENDING,直接結束
if (that.status !== PENDING) return;
// 將狀態改為RESOLVED
that.status = RESOLVED;
// 保存value數據
that.data = value;
// 如果有待執行callback函數,立即異步執行回調函數 onResolved
if (that.callbacks.length > 0) {
// 放入隊列中執行所有成功的回調
setTimeout(() => {
that.callbacks.forEach(callbacksObj => {
callbacksObj.onResolved(value);
});
});
};
};
function reject(reason) {
// 如果當前狀態不是PENDING,直接結束
if (that.status !== PENDING) return;
// 將狀態改為REJECTED
that.status = REJECTED;
// 保存value數據
that.data = reason;
// 如果有待執行的callback函數,立即異步執行回調函數onREJECTED
if (that.callbacks.length > 0) {
setTimeout(() => {
that.callbacks.forEach((callbacksObj) => {
callbacksObj.onRejected(reason);
});
});
};
};
// 立即同步執行excutor
try {
excutor(resolve, reject);
} catch (error) { // 如果執行器拋出異常,promise對象變為REJECTED狀態
reject(error);
}
};
/*
Promise原型對象的then()
指定成功和失敗的回調函數
返回一個新的promise對象
*/
Promise.prototype.then = function (onResolved, onRejected) {
// 指定兩個回調函數的默認值(必須是函數)
onResolved = typeof onResolved === 'function' ? onResolved : value => value; // 向后傳遞成功的value
// 指定默認的失敗的回調(實現錯誤 / 異常穿透的關鍵點)
onRejected = typeof onRejected === 'function' ? onRejected : reason => { throw reason }; // 向后傳遞失敗的reason
const that = this;
// 返回一個新的promise對象
return new Promise((resolve, reject) => {
/*
調用指定回調函數處理, 根據執行結果,改變return的promise的狀態。
*/
function handle(callback) {
/*
1. 如果拋出異常,return的promise就會失敗,reason 就是 error
2. 如果回調函數返回的不是promise, return的promise就會是成功, value就是返回的值
3. 如果回調函數返回的是promise, return的promise結果就是這個promise 的結果
*/
try {
const result = callback(that.data);
if (result instanceof Promise) {
result.then(resolve, reject);
} else {
resolve(result);
}
} catch (error) {
reject(error);
};
}
// 當前狀態還是pending狀態,將回調函數保存起來
if (that.status === PENDING) {
that.callbacks.push({
onResolved() {
handle(onResolved);
},
onRejected() {
handle(onRejected);
},
});
} else if (that.status === RESOLVED) { // 如果當前是resolved狀態,異步執行onResolved并改變return的promise狀態
setTimeout(() => {
handle(onResolved);
});
} else { // 如果當前是resolved狀態,異步執行onRejected并改變return的promise狀態。
setTimeout(() => {
handle(onRejected);
});
}
})
};
/*
Promise原型對象的catch()
指定失敗的回調函數
返回一個新的promise對象
*/
Promise.prototype.catch = function (onRejected) {
return this.then(undefined, onRejected);
};
/*
Promise函數對象的resolve方法
返回一個指定結果的成功的promise
*/
Promise.resolve = function (value) {
// 返回一個成功的promise
return new Promise((resolve, reject) => {
if (value instanceof Promise) {
// 是promise的話,使用value的結果作為promise的結果
value.then(resolve, reject);
} else {
// promise變為成功,數據是value
resolve(value);
};
});
};
/*
Promise函數的reject方法
返回一個指定結果的失敗的promise
*/
Promise.reject = function (reason) {
return new Promise((resolve, reject) => {
reject(reason);
});
};
/*
Promise函數的all方法
返回一個promise, 只有當所有promise都成功時才成功,否則只要有一個失敗的就失敗
*/
Promise.all = function (promiseArr) {
const valuesArr = new Array(promiseArr.length); // 保存所有成功的value值
let resolvedCount = 0; // 用來保存成功的promise數量
return new Promise((resolve, reject) => {
// 遍歷promise獲取每個Promise的結果
promiseArr.forEach((pObj, index) => {
Promise.resolve(pObj).then(
value => {
// 當前的p成功,將成功的value放入數組中
valuesArr[index] = value; // 注意順序問題,按照promiseArr的順序放入
resolvedCount++;
// 如果全部成功了,將return的promise改變成功
if (resolvedCount === promiseArr.length) {
resolve(valuesArr);
};
},
reason => { // 只要有一個失敗了,return的promise就失敗了
reject(reason);
}
)
})
})
};
/*
Promise函數的race方法
返回一個promise,其結果由第一個完成的promise決定,第一個失敗就是失敗,否則就是成功
*/
Promise.race = function (promiseArr) {
return new Promise((resolve, reject) => {
// 遍歷每個promise獲取結果
promiseArr.forEach((pObj, index) => {
if (pObj instanceof Promise) { // 可以判斷pObj是不是promise,也可以 Promie.resolve(pObj).then()
pObj.then(
value => { // 一旦有成功的,將return 變為成功
resolve(value);
},
reason => {
reject(reason);
},
);
} else {
resolve(pObj);
};
});
});
};
/*
Promise函數對象上的 resolveDelay方法
返回一個promise對象,它在指定的時間后才確定結果
*/
Promise.resolveDelay = function (value, time) {
return new Promise((resolve, reject) => {
setTimeout(() => {
if (value instanceof Promise) {
value.then(resolve, reject);
} else {
resolve(value);
}
}, time);
});
};
/*
Promise函數對象上的 rejectDelay方法
返回一個promise對象,它在指定的時間后才失敗
*/
Promise.rejectDelay = function (reason, time) {
return new Promise((resolve, reject) => {
setTimeout(() => {
reject(reason);
}, time);
});
};
// 向外暴露Promise函數
window.Promise = Promise;
})(window);
測試代碼:
const p4 = new Promise((resolve) => {
setTimeout(() => {
resolve(4);
}, 1000);
});
const p1 = Promise.resolve(1);
const p3 = Promise.resolve(Promise.reject(3));
const p5 = Promise.resolve(5);
const p2 = Promise.reject(Promise.resolve(2));
p4.then((value) => {
console.log("p4", value);
});
p1.then((value) => console.log("p1", value));
p2.catch((value) => console.log("p2", value));
p3.catch((reason) => console.log("p3", reason));
const pAll = Promise.all([p4, 2, p1, p5]);
pAll.then(
(values) => {
console.log("pAll onResolved()", values);
},
(reason) => {
console.log("pAll onRejected()", reason);
}
);
const pRace = Promise.race([p1, p3, p2, p5, p4]);
pRace.then(
(value) => {
console.log("pRace onResolved()", value);
},
(reason) => {
console.log("pRace onRejected()", reason);
}
);
const p6 = Promise.resolveDelay(66, 2000);
const p7 = Promise.rejectDelay(77, 3000);
p6.then((value) => console.log("p6", value));
p7.catch((reason) => console.log("p7", reason));
撒花??ヽ(°▽°)ノ?