三種狀態(tài)
pending,resolved,rejected,狀態(tài)一旦確定不可更改
class MyPromise {
constructor(handle) {
this['[[PromiseStatus]]'] = "pending"
this['[[PromiseValue]]'] = undefined
handle(this.resolve.bind(this), this.reject.bind(this))
}
resolve(val) {
if (this['[[PromiseStatus]]'] === "pending") {
this['[[PromiseStatus]]'] = "resolved"
this['[[PromiseValue]]'] = val
}
}
reject(err) {
if (this['[[PromiseStatus]]'] === "pending") {
this['[[PromiseStatus]]'] = "rejected"
this['[[PromiseValue]]'] = err
}
}
}
then方法
需要異步執(zhí)行resolveFn和rejectFn,不然MyPromise里執(zhí)行resolve或reject時(shí),then里面的方法還沒讀取到。
可以用MutationObserver模擬微任務(wù)。
class MyPromise {
constructor(handle) {
this['[[PromiseStatus]]'] = "pending"
this['[[PromiseValue]]'] = undefined
handle(this.resolve.bind(this), this.reject.bind(this))
}
resolve(val) {
if (this['[[PromiseStatus]]'] === "pending") {
this['[[PromiseStatus]]'] = "resolved"
this['[[PromiseValue]]'] = val
const run = () => {
this.resolveFn(val)
}
const observer = new MutationObserver(run);
observer.observe(document.body, {
attributes: true
});
document.body.setAttribute("key", "value");
}
}
reject(err) {
if (this['[[PromiseStatus]]'] === "pending") {
this['[[PromiseStatus]]'] = "rejected"
this['[[PromiseValue]]'] = err
const run = () => {
this.rejectFn(err)
}
const observer = new MutationObserver(run);
observer.observe(document.body, {
attributes: true
});
document.body.setAttribute("key", "value");
}
}
then(resolveFn, rejectFn) {
this.resolveFn = resolveFn
this.rejectFn = rejectFn
}
}
支持并列多個(gè)then
并列的then都是獲取到調(diào)用then的Promise對象的值。
let p = new Promise((resolve, reject) => {
resolve('success');
// reject("err");
})
p.then(res => {
console.log(1, res);
})
p.then(res => {
console.log(2, res);
})
// 1 "success"
// 2 "success"
需要用一個(gè)數(shù)組存儲then傳進(jìn)來的函數(shù)。在resolved或rejected后遍歷執(zhí)行。
class MyPromise {
constructor(handle) {
this['[[PromiseStatus]]'] = "pending"
this['[[PromiseValue]]'] = undefined
this.resolveQueue = []
this.rejectQueue = []
handle(this.resolve.bind(this), this.reject.bind(this))
}
resolve(val) {
if (this['[[PromiseStatus]]'] === "pending") {
this['[[PromiseStatus]]'] = "resolved"
this['[[PromiseValue]]'] = val
const run = () => {
let cb;
// 直接刪除而不是forEach遍歷執(zhí)行,是因?yàn)槎际怯玫氖录O(jiān)聽,不然后面會被重復(fù)執(zhí)行
while (cb = this.resolveQueue.shift()) {
cb && cb(val);
}
}
const observer = new MutationObserver(run);
observer.observe(document.body, {
attributes: true
});
document.body.setAttribute("key", "value");
}
}
reject(err) {
if (this['[[PromiseStatus]]'] === "pending") {
this['[[PromiseStatus]]'] = "rejected"
this['[[PromiseValue]]'] = err
const run = () => {
let cb;
while (cb = this.rejectQueue.shift()) {
cb && cb(err);
}
}
const observer = new MutationObserver(run);
observer.observe(document.body, {
attributes: true
});
document.body.setAttribute("key", "value");
}
}
then(resolveFn, rejectFn) {
this.resolveQueue.push(resolveFn)
this.rejectQueue.push(rejectFn)
}
}
鏈?zhǔn)秸{(diào)用then
then執(zhí)行返回的是一個(gè)新的promise對象,
可以返回正常值,若返回promise對象,會自動(dòng)解析入?yún)鬟f給下一個(gè)then。
let p2 = new Promise((resolve, reject) => {
resolve("success");
// reject("err");
}).then(res => {
console.log(1, res);//1 "success"
return 1
}).then(res => {
console.log(2, res);//2 1
return new Promise((resolve) => {
resolve('2promise')
})
}).then(res => {
console.log(3, res);//3 "2promise"
})
class MyPromise {
constructor(handle) {
this['[[PromiseStatus]]'] = "pending"
this['[[PromiseValue]]'] = undefined
this.resolveQueue = []
this.rejectQueue = []
handle(this.resolve.bind(this), this.reject.bind(this))
}
resolve(val) {
if (this['[[PromiseStatus]]'] === "pending") {
this['[[PromiseStatus]]'] = "resolved"
this['[[PromiseValue]]'] = val
const run = () => {
let cb;
while (cb = this.resolveQueue.shift()) {
cb && cb(val);
}
}
const observer = new MutationObserver(run);
observer.observe(document.body, {
attributes: true
});
document.body.setAttribute("key", "value");
}
}
reject(err) {
if (this['[[PromiseStatus]]'] === "pending") {
this['[[PromiseStatus]]'] = "rejected"
this['[[PromiseValue]]'] = err
const run = () => {
let cb;
while (cb = this.rejectQueue.shift()) {
cb && cb(err);
}
}
const observer = new MutationObserver(run);
observer.observe(document.body, {
attributes: true
});
document.body.setAttribute("key", "value");
}
}
then(resolveFn, rejectFn) {
return new MyPromise((resolve, reject) => {
// 返回一個(gè)新的Promise
// 需要取到上一個(gè)then的返回值
// 判斷返回的結(jié)果是正常值直接返回,是Promise值需要取出來返回
function TResolveFn(val) {
let result = resolveFn && resolveFn(val)
if (result instanceof MyPromise) {
result.then(res => {
resolve(res)
}, err => {
reject(err)
})
} else {
resolve(result)
}
}
this.resolveQueue.push(TResolveFn)
function TRejectFn(val) {
let result = rejectFn && rejectFn(val)
if (result instanceof MyPromise) {
result.then(res => {
resolve(res)
}, err => {
reject(err)
})
} else {
reject(result)
}
}
this.rejectQueue.push(TRejectFn)
})
}
}
catch和finally方法
catch(fn) {
return this.then(undefined, fn);
}
finally(fn) {
//不管成功失敗都會執(zhí)行
this.then(fn, fn)
}
靜態(tài)方法
resolve
返回一個(gè)成功狀態(tài)Promise
static resolve(result) {
return new MyPromise((resolve) => {
resolve(result)
})
}
reject
返回一個(gè)失敗狀態(tài)Promise
static reject(result) {
return new MyPromise((resolve, reject) => {
reject(result)
})
}
all
接受一個(gè)Promise數(shù)組,返回一個(gè)新的Promise,
如果Promise都成功,按數(shù)組順序返回成功狀態(tài),
若有一個(gè)失敗,返回最先被reject的值。
static all(promiseAry) {
let result = []
let num = 0
return new MyPromise((resolve, reject) => {
for (let i = 0; i < promiseAry.length; i++) {
promiseAry[i].then((res) => {
result[i] = res
num++
if (num === promiseAry.length) {
resolve(result)
}
}, err => {
reject(err)
})
}
})
}
race
接受一個(gè)Promise數(shù)組,返回一個(gè)新的Promise,
返回最快響應(yīng)的Promise
static race(promiseAry) {
return new MyPromise((resolve, reject) => {
for (let i = 0; i < promiseAry.length; i++) {
promiseAry[i].then((res) => {
resolve(res)
}, err => {
reject(err)
})
}
})
}
allSettled
接受一個(gè)Promise數(shù)組,返回一個(gè)新的Promise,
不管成功和失敗都會返回,數(shù)據(jù)結(jié)構(gòu)如下
//成功:
{
status: "fulfilled"
value: "success"
}
//失敗
{
reason: "err"
status: "rejected"
}
static allSettled(promiseAry) {
let result = []
let num = 0
return new MyPromise((resolve, reject) => {
for (let i = 0; i < promiseAry.length; i++) {
promiseAry[i].then((res) => {
result[i] = {
status: "fulfilled",
value: res
}
num++
if (num === promiseAry.length) {
resolve(result)
}
}, err => {
result[i] = {
status: "rejected",
value: err
}
num++
if (num === promiseAry.length) {
resolve(result)
}
})
}
})
}