聲明:本文是學習珠峯培訓視頻,模仿實現的Promise,通過了 promises-aplus-tests測試,文章最下面有截圖。
const PENDING = 'pending'; // 初始態
const FULFILLED = 'fulFilled'; // 成功態
const REJECTED = 'rejected'; // 失敗態
function Promise(exector) {
let self = this; // 先緩存當前的 Promise實例
self.status = PENDING; // 設置狀態
self.onResolvedCallbacks = []; // 定義存放成功回調的數組
self.onRejectedCallbacks = []; // 定義存放失敗回調的數組
function resolve(value) {
if (value instanceof Promise) {
return value.then(resolve, reject);
}
// 當調用此方法的時候,如果是pending狀態,則轉成 成功態
if (self.status === PENDING) {
self.status = FULFILLED;
self.value = value; // 成功後會得到一個值,這個值不能改
// 調用所有成功的回調
self.onResolvedCallbacks.forEach(cb => cb(self.value))
}
}
function reject(reason) {
// 如果是初始態,則轉成失敗態
if (self.status === PENDING) {
self.status = REJECTED;
self.value = reason; // 失敗的原因 給value
// 調用所有失敗的回調
self.onRejectedCallbacks.forEach(cb => cb(self.value))
}
}
try {
exector(resolve, reject); // 因爲此函數執行的時候,可能出異常,所以需要捕獲,如果出錯了,需要用錯誤對象Reject
} catch (e) {
reject(e); // 如果執行失敗了,用失敗的原因reject這個Promise
}
}
// onFulfilled用來接收Promise成功的值或失敗的原因
Promise.prototype.then = function (onFulfilled, onRejected) {
// 如果成功和失敗的回調沒有傳,則表示這個then沒有任何邏輯,只會把值往後拋
onFulfilled = typeof onFulfilled == 'function' ? onFulfilled : value => value;
onRejected = typeof onRejected == 'function' ? onRejected : reason => {
throw reason
};
let self = this;
let promise2;
// 如果當前的Promise狀態已經是成功態了,onFulfilled直接取值
if (self.status == FULFILLED) {
return promise2 = new Promise(function (resolve, reject) {
setTimeout(function () {
try {
let x = onFulfilled(self.value)
// 如果獲取到了返回值,會走解析Promise的過程
resolvePromise(promise2, x, resolve, reject);
} catch (e) {
// 如果執行成功的回調中出問題了,用錯誤原因把promise2 reject
reject(e);
}
})
})
}
if (self.status == REJECTED) {
return promise2 = new Promise(function (resolve, reject) {
setTimeout(function () {
try {
let x = onRejected(self.value);
resolvePromise(promise2, x, resolve, reject);
} catch (e) {
reject(e);
}
})
})
}
if (self.status == PENDING) {
return promise2 = new Promise(function (resolve, reject) {
self.onResolvedCallbacks.push(function () {
setTimeout(function () {
try {
let x = onFulfilled(self.value);
resolvePromise(promise2, x, resolve, reject);
} catch (e) {
reject(e);
}
})
})
self.onRejectedCallbacks.push(function () {
setTimeout(function () {
try {
let x = onRejected(self.value);
resolvePromise(promise2, x, resolve, reject);
} catch (e) {
reject(e);
}
})
})
})
}
function resolvePromise(promise2, x, resolve, reject) {
if (promise2 === x) {
return reject(new TypeError('循環引用'));
}
let called = false; // 用於判斷promise2是否已經resolve或reject
// if (x instanceof Promise) {
// if (x.status === PENDING) {
// setTimeout(function () {
// x.then(function (y) {
// resolvePromise(promise2, 2, resolve, reject)
// }, function (e) {
// reject(e)
// })
// })
// } else {
// setTimeout(function () {
// x.then(resolve, reject);
// })
// }
// // x 是一個 thenable對象或函數,只要有then方法的對象
// } else
if (x != null && ((typeof x == 'object') || (typeof x === 'function'))) {
// 以下代碼 主要用於我們的Promise和別人的Promise進行交互,編寫這種代碼,要考慮到
// 兼容性,允許別人出錯
try {
let then = x.then;
if (typeof then == 'function') {
// 有些promise會同時執行成功和失敗的回調
then.call(x, function (y) {
// 如果promise2已經成功或者失敗了,則不需要再處理了
if (called) return;
called = true;
resolvePromise(promise2, y, resolve, reject);
}, function (err) {
if (called) return;
called = true;
reject(err);
})
} else {
// 如果promise2已經成功或者失敗了,則不需要再處理了
if (called) return;
called = true;
// 到此的話 x 不是一個 thenable對象,那直接把他rosolve掉
resolve(x);
}
} catch (e) {
if (called) return;
called = true;
reject(e);
}
} else {
// 如果promise2已經成功或者失敗了,則不需要再處理了
if (called) return;
called = true;
// 如果x 是一個普通的值,就用x的值去resolve promise2
resolve(x)
}
}
}
Promise.prototype.catch = function (onRejected) {
// catch 的原理就是隻傳失敗的回調
this.then(null, onRejected);
}
Promise.deferred = Promise.defer = function () {
let defer = {};
defer.promise = new Promise(function (resolve, reject) {
defer.resolve = resolve;
defer.reject = reject;
})
return defer;
}
module.exports = Promise;