Promise
實(shí)現(xiàn)一個(gè)符合 Promise/A+ 規(guī)范的 MyPromise秒际,并實(shí)現(xiàn) resolve悬赏、reject、all娄徊、race闽颇、defer、deferred等靜態(tài)方法寄锐。
MyPromise
作用:創(chuàng)建
MyPromise
實(shí)例兵多。PromiseMyPromise接收一個(gè)回掉函數(shù)
executor
-
MyPromise狀態(tài)
-
pending
- 可以轉(zhuǎn)換成 fulfilled 或 rejected
-
fulfilled
- 不可改變成其他狀態(tài)
-
rejected
- 不可改變成其他狀態(tài)
-
-
onFulfilledCallbacks
和onRejectedCallbacks
兩個(gè)數(shù)組,數(shù)組每一項(xiàng)是一個(gè)函數(shù)橄仆。分別接收
then
里面的第一個(gè)參數(shù)和第二個(gè)參數(shù)剩膘。狀態(tài)是
pending
的回掉函數(shù)。
-
resolve
promise
的狀態(tài)是fulfilled
異常是的處理函數(shù)-
接收
value
參數(shù)如果是
promise
盆顾,執(zhí)行then
怠褐。如果不是
promise
,把value
做為參數(shù)傳給onFulfilledCallbacks
里的每個(gè)函數(shù)您宪。
-
reject
promise
的狀態(tài)是rejected
異常是的處理函數(shù)接收
reason
參數(shù)奈懒,把reason
做為參數(shù)傳給onRejectedCallbacks
里的每個(gè)函數(shù)奠涌。
執(zhí)行
executor
,如果有異常筐赔,拋給reject
因?yàn)?code>Promise是在同步代碼執(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);
}
}
MyPromise.prototype.then
作用:接收兩個(gè)函數(shù)參數(shù),第一個(gè)函數(shù)的參數(shù)是
resolve
傳入的參數(shù)茴丰,第二個(gè)參數(shù)是reject
傳入的參數(shù)达皿。Promise#then-
onFulfilled
MyPromise
成功時(shí)執(zhí)行的方法resolve
的參數(shù)會(huì)作為value
傳給onFulfilled
-
onRejected
MyPromise
失敗時(shí)執(zhí)行的方法reject
的參數(shù)會(huì)作為value
傳給onRejected
返回一個(gè)
MyPromise
實(shí)例newPromise
,方便鏈?zhǔn)秸{(diào)用-
對(duì)三種狀態(tài)分別處理
每個(gè)狀態(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
的最后一位
- 狀態(tài)待定溜哮,把
resolutionPromise
后面細(xì)說用
catch
捕獲異常滔金,執(zhí)行reject
MyPromise.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;
/**
* 分別處理實(shí)例的三種狀態(tài)
*/
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
作用:捕獲異常
返回
MyPromise
MyPromise.prototype.catch = function (onRejected) {
return this.then(undefined, onRejected);
};
The Promise Resolution Procedure
Promise解析過程,是以一個(gè)
promise
茂嗓、一個(gè)值x
及resolve
,reject
做為參數(shù)的抽象過程promise
等于x
餐茵,reject
拋出異常new TypeError('循環(huán)引用')
x
如果不是對(duì)象(不包括null
)或者函數(shù),執(zhí)行resolve(x)
-
獲取
x.then
賦值給then
-
then
如果是function
把
x
做為this
調(diào)用then
述吸,第一個(gè)參數(shù)是resolvePromise
忿族,第二個(gè)參數(shù)是rejectPromise
resolvePromise
和rejectPromise
只有第一次調(diào)用有效resolvePromise
參數(shù)為y
,執(zhí)行resolutionPromise(promise, y, resolve, reject)
rejectPromise
參數(shù)為r
蝌矛,執(zhí)行reject(r)
-
then
如果不是function
- 執(zhí)行
resolve(x)
- 執(zhí)行
-
-
用捕獲上一步的異常
執(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);
}
}
MyPromise 靜態(tài)方法
MyPromise.all
- 作用:Promise.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
- 作用:Promise.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