Promise
實(shí)現(xiàn)一個符合 Promise/A+ 規(guī)范的 MyPromise,并實(shí)現(xiàn) resolve、reject、all、race、defer、deferred等靜態(tài)方法。
MyPromise
作用:創(chuàng)建 MyPromise實(shí)例。PromiseMyPromise接收一個回掉函數(shù) executorMyPromise狀態(tài) - pending
- 可以轉(zhuǎn)換成 fulfilled 或 rejected
- fulfilled
- rejected
onFulfilledCallbacks 和 onRejectedCallbacks - 兩個數(shù)組,數(shù)組每一項(xiàng)是一個函數(shù)。分別接收then里面的第一個參數(shù)和第二個參數(shù)。
- 狀態(tài)是 pending 的回掉函數(shù)。
resolve - promise的狀態(tài)是fulfilled異常是的處理函數(shù)
- 接收 value 參數(shù)
- 如果是promise,執(zhí)行then。
- 如果不是promise,把value做為參數(shù)傳給onFulfilledCallbacks里的每個函數(shù)。
reject - promise的狀態(tài)是rejected異常是的處理函數(shù)
- 接收 reason 參數(shù),把reason做為參數(shù)傳給onRejectedCallbacks里的每個函數(shù)。
執(zhí)行 executor,如果有異常,拋給reject因?yàn)镻romise是在同步代碼執(zhí)行完成后再執(zhí)行,所以要把Mypromise的執(zhí)行方法resolve和reject放在異步隊(duì)列里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);}
}
復(fù)制代碼MyPromise.prototype.then
作用:接收兩個函數(shù)參數(shù),第一個函數(shù)的參數(shù)是 resolve傳入的參數(shù),第二個參數(shù)是 reject傳入的參數(shù)。Promise#thenonFulfilled - MyPromise 成功時執(zhí)行的方法
- resolve 的參數(shù)會作為value傳給 onFulfilled
onRejected - MyPromise 失敗時執(zhí)行的方法
- reject 的參數(shù)會作為value傳給 onRejected
返回一個 MyPromise 實(shí)例 newPromise,方便鏈?zhǔn)秸{(diào)用對三種狀態(tài)分別處理 - 每個狀態(tài)中創(chuàng)建 newPromise
- fulfilled
- 直接執(zhí)行 onFulfilled,返回值x
- 把newPromise、x以及newPromise里的resolve、reject做為參數(shù)傳給 resolutionPromise
- 把 MyPromise 的參數(shù)放在異步隊(duì)列里
- rejected
- 直接執(zhí)行 onRejected,返回值x
- 把newPromise、x以及newPromise里的resolve、reject做為參數(shù)傳給 resolutionPromise
- 把 MyPromise 的參數(shù)放在異步隊(duì)列里
- pending
- 狀態(tài)待定,把fulfilled和rejected里的異步函數(shù)分別加到 onFulfilledCallbacks 和 onRejectedCallbacks的最后一位
resolutionPromise 后面細(xì)說用catch捕獲異常,執(zhí)行 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;
};
復(fù)制代碼MyPromise.prototype.catch
作用:捕獲異常返回 MyPromiseMyPromise.prototype.catch =
function (onRejected) {
return this.then(
undefined, onRejected);
};
復(fù)制代碼The Promise Resolution Procedure
Promise解析過程,是以一個 promise、一個值 x及resolve, reject做為參數(shù)的抽象過程promise 等于 x,reject 拋出異常 new TypeError('循環(huán)引用')x如果不是對象(不包括 null)或者函數(shù),執(zhí)行 resolve(x)獲取 x.then 賦值給 then - then 如果是 function
- 把 x做為 this 調(diào)用then,第一個參數(shù)是 resolvePromise,第二個參數(shù)是 rejectPromise
- resolvePromise和 rejectPromise只有第一次調(diào)用有效
- resolvePromise參數(shù)為 y,執(zhí)行 resolutionPromise(promise, y, resolve, reject)
- rejectPromise參數(shù)為 r,執(zhí)行 reject(r)
- then 如果不是 function
用捕獲上一步的異常 - 執(zhí)行 reject(e)
- 如果執(zhí)行過 resolvePromise或 rejectPromise,忽略
function resolutionPromise(promise, x, resolve, reject) {
if (promise === x) {reject(
new TypeError(
'循環(huán)引用'));}
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);}
}
復(fù)制代碼MyPromise 靜態(tài)方法
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;}});}});
};
復(fù)制代碼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;}});}})
};
復(fù)制代碼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);}})
};
復(fù)制代碼MyPromise.reject
MyPromise.reject =
function (e) {
return new MyPromise(
function (resolve, reject) {reject(e);})
};
復(fù)制代碼test
- npm i -g promises-aplus-tests
- promises-aplus-tests Promise.js
源碼
參考資料
- Promise/A+規(guī)范
- Promise/A+規(guī)范(英文)
- JavaScript Promise迷你書(中文版)
總結(jié)
以上是生活随笔為你收集整理的实现一个符合 Promise/A+ 规范的 MyPromise的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
如果覺得生活随笔網(wǎng)站內(nèi)容還不錯,歡迎將生活随笔推薦給好友。