Promise
實現一個符合 Promise/A+ 規范的 MyPromise,并實現 resolve、reject、all、race、defer、deferred等靜態方法。
MyPromise
作用:創建 MyPromise實例。PromiseMyPromise接收一個回掉函數 executorMyPromise狀態 - pending
- 可以轉換成 fulfilled 或 rejected
- fulfilled
- rejected
onFulfilledCallbacks 和 onRejectedCallbacks - 兩個數組,數組每一項是一個函數。分別接收then里面的第一個參數和第二個參數。
- 狀態是 pending 的回掉函數。
resolve - promise的狀態是fulfilled異常是的處理函數
- 接收 value 參數
- 如果是promise,執行then。
- 如果不是promise,把value做為參數傳給onFulfilledCallbacks里的每個函數。
reject - promise的狀態是rejected異常是的處理函數
- 接收 reason 參數,把reason做為參數傳給onRejectedCallbacks里的每個函數。
執行 executor,如果有異常,拋給reject因為Promise是在同步代碼執行完成后再執行,所以要把Mypromise的執行方法resolve和reject放在異步隊列里function MyPromise(executor) {
if (
typeof executor !==
'function') {
throw new TypeError(
'Promise resolver ' + executor +
' is not a function');}
let self =
this;
this.status =
'pending';
this.value =
undefined;
this.reason =
undefined;
this.onFulfilledCallbacks = [];
this.onRejectedCallbacks = [];
function resolve(value) {
if (value
instanceof MyPromise) {
return value.then(resolve, reject);}
if (self.status ===
'pending') {self.value = value;self.status =
'fulfilled';self.onFulfilledCallbacks.forEach(
item => item(value));}}
function reject(reason) {
if (self.status ===
'pending') {self.reason = reason;self.status =
'rejected'; self.onRejectedCallbacks.forEach(
item => item(reason));}}
try {executor(resolve, reject);}
catch (e) {reject(e);}
}
復制代碼MyPromise.prototype.then
作用:接收兩個函數參數,第一個函數的參數是 resolve傳入的參數,第二個參數是 reject傳入的參數。Promise#thenonFulfilled - MyPromise 成功時執行的方法
- resolve 的參數會作為value傳給 onFulfilled
onRejected - MyPromise 失敗時執行的方法
- reject 的參數會作為value傳給 onRejected
返回一個 MyPromise 實例 newPromise,方便鏈式調用對三種狀態分別處理 - 每個狀態中創建 newPromise
- fulfilled
- 直接執行 onFulfilled,返回值x
- 把newPromise、x以及newPromise里的resolve、reject做為參數傳給 resolutionPromise
- 把 MyPromise 的參數放在異步隊列里
- rejected
- 直接執行 onRejected,返回值x
- 把newPromise、x以及newPromise里的resolve、reject做為參數傳給 resolutionPromise
- 把 MyPromise 的參數放在異步隊列里
- pending
- 狀態待定,把fulfilled和rejected里的異步函數分別加到 onFulfilledCallbacks 和 onRejectedCallbacks的最后一位
resolutionPromise 后面細說用catch捕獲異常,執行 rejectMyPromise.prototype.then =
function (onFulfilled, onRejected) {
let self =
this;
typeof onFulfilled !==
'function' && (onFulfilled =
function (value) {
return value;});
typeof onRejected !==
'function' && (onRejected =
function (reason) {
throw reason;});
let newPromise;
if (self.status ===
'fulfilled') {newPromise =
new MyPromise(
function (resolve, reject) {setTimeout(
function () {
try {
let x = onFulfilled(self.value);resolutionPromise(newPromise, x, resolve, reject);}
catch (e) {reject(e);}});});}
if (self.status ===
'rejected') {newPromise =
new MyPromise(
function (resolve, reject) {setTimeout(
function () {
try {
let x = onRejected(self.reason);resolutionPromise(newPromise, x, resolve, reject);}
catch (e) {reject(e);}});});}
if (self.status ===
'pending') {newPromise =
new MyPromise(
function (resolve, reject) {self.onFulfilledCallbacks.push(
function (value) {setTimeout(
function () {
try {
let x = onFulfilled(value);resolutionPromise(newPromise, x, resolve, reject);}
catch (e) {reject(e);}});});self.onRejectedCallbacks.push(
function (reason) {setTimeout(
function () {
try {
let x = onRejected(reason);resolutionPromise(newPromise, x, resolve, reject);}
catch (e) {reject(e);}});});});}
return newPromise;
};
復制代碼MyPromise.prototype.catch
作用:捕獲異常返回 MyPromiseMyPromise.prototype.catch =
function (onRejected) {
return this.then(
undefined, onRejected);
};
復制代碼The Promise Resolution Procedure
Promise解析過程,是以一個 promise、一個值 x及resolve, reject做為參數的抽象過程promise 等于 x,reject 拋出異常 new TypeError('循環引用')x如果不是對象(不包括 null)或者函數,執行 resolve(x)獲取 x.then 賦值給 then - then 如果是 function
- 把 x做為 this 調用then,第一個參數是 resolvePromise,第二個參數是 rejectPromise
- resolvePromise和 rejectPromise只有第一次調用有效
- resolvePromise參數為 y,執行 resolutionPromise(promise, y, resolve, reject)
- rejectPromise參數為 r,執行 reject(r)
- then 如果不是 function
用捕獲上一步的異常 - 執行 reject(e)
- 如果執行過 resolvePromise或 rejectPromise,忽略
function resolutionPromise(promise, x, resolve, reject) {
if (promise === x) {reject(
new TypeError(
'循環引用'));}
let then, called;
if (x !==
null && (
typeof x ===
'object' ||
typeof x ===
'function')) {
try {then = x.then;
if (
typeof then ===
'function') {then.call(x,
function (y) {
if (called)
return;called =
true;resolutionPromise(promise, y, resolve, reject);},
function (r) {
if (called)
return;called =
true;reject(r);})}
else {resolve(x);}}
catch (e) {
if (called)
return;reject(e);}}
else {resolve(x);}
}
復制代碼MyPromise 靜態方法
MyPromise.all
MyPromise.all =
function (promises) {
let called =
false;
return new MyPromise(
function (resolve, reject) {
let newArr = [], count =
0;
for (
let i =
0; i < promises.length; i++) {
let item = promises[i];
if (!(item
instanceof MyPromise)) {item = MyPromise.resolve(item);}item.then(
function (data) {
if (!called) {newArr[i] = data;
if (i == count) {resolve(newArr);count++;}}},
function (e) {
if (!called) {reject(e);called =
true;}});}});
};
復制代碼MyPromise.race
MyPromise.race =
function (promises) {
return new MyPromise(
function (resolve, reject) {
let called =
false;
for (
let i =
0; i < promises.length; i++) {
let item = promises[i];
if (!(item
instanceof MyPromise)) {item = MyPromise.resolve(item);}item.then(
function (data) {
if (!called) {resolve(data);called =
true;}},
function (e) {
if (!called) {reject(e);called =
true;}});}})
};
復制代碼MyPromise.resolve
MyPromise.resolve =
function (value) {
if (value
instanceof MyPromise) {
return value;}
return new MyPromise(
function (resolve, reject) {
if (
typeof value !==
null &&
typeof value ===
'object' &&
typeof value.then ===
'function') {value.then();}
else {resolve(value);}})
};
復制代碼MyPromise.reject
MyPromise.reject =
function (e) {
return new MyPromise(
function (resolve, reject) {reject(e);})
};
復制代碼test
- npm i -g promises-aplus-tests
- promises-aplus-tests Promise.js
源碼
參考資料
- Promise/A+規范
- Promise/A+規范(英文)
- JavaScript Promise迷你書(中文版)
總結
以上是生活随笔為你收集整理的实现一个符合 Promise/A+ 规范的 MyPromise的全部內容,希望文章能夠幫你解決所遇到的問題。
如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。