javascript Promise底层实现
Posted 任天镗
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了javascript Promise底层实现相关的知识,希望对你有一定的参考价值。
class Promise {
constructor(handle) {
if (typeof handle !== "function") {
throw new Error("promise must accept a function as a parameter");
}
// 定义三种状态配置
this.STATUS = {
PENDING: "pending",
FULFILLED: "fulfilled",
REJECTED: "rejected"
};
// 初始化状态
this._status = this.STATUS.PENDING;
// 初始化值
this._value = undefined;
// 成功状态需要执行的任务队列
this._fulfilledQueues = [];
// 失败状态需要执行的任务队列
this._rejectedQueues = [];
// 执行handle
try {
handle(this._resolve.bind(this), this._reject.bind(this));
} catch (err) {
this._reject(err);
}
}
// Object.prototype.toString.call(promiseObj) === "[object Promise]"
get [Symbol.toStringTag](){
return "Promise"
}
_runMicroTask(callback) {
// 使用浏览器MutationObserver WEB.API实现then方法的微任务机制
let count = 0;
const observer = new MutationObserver(callback);
// 创建文本节点,节约资源
const textNode = document.createTextNode(String(count));
observer.observe(textNode, {
// 当文本改变时触发回调
characterData: true
});
// 改变文本,回调callback触发
textNode.data = String(++count);
}
_resolve(val) {
if (this._status !== this.STATUS.PENDING) return;
const onFulfilled = v => {
this._status = this.STATUS.FULFILLED;
this._value = v;
let cb;
while ((cb = this._fulfilledQueues.shift())) {
cb(v);
}
};
const onRejected = err => {
this._status = this.STATUS.REJECTED;
this._value = err;
let cb;
while ((cb = this._rejectedQueues.shift())) {
cb(err);
}
};
// 依次执行成功队列中的函数,并清空队列
const run = () => {
if (val instanceof Promise) {
// 如果入参是一个Promise,则val的status及value值决定了当前promise实例的status和value值
val.then(onFulfilled, onRejected);
} else {
onFulfilled(val);
}
};
this._runMicroTask(run);
}
_reject(val) {
if (this._status !== this.STATUS.PENDING) return;
// 依次执行失败队列中的函数,并清空队列
const run = () => {
this._status = this.STATUS.REJECTED;
this._value = val;
let cb;
while ((cb = this._rejectedQueues.shift())) {
cb(val);
}
};
this._runMicroTask(run);
}
then(onFulfilled, onRejected) {
// then支持链式调用,返回一个新的promise
return new Promise((resolve, reject) => {
const handleResolve = value => {
try {
if (typeof onFulfilled !== "function") {
// 如果onFulfilled不是函数,则直接返回当前promise的value值
resolve(value);
} else {
const res = onFulfilled(value);
// Promise.prototype 是否存在于res的原型链上,是则说明res是Promise实例
if (res instanceof Promise) {
res.then(resolve, reject);
} else {
resolve(res);
}
}
} catch (err) {
reject(err);
}
};
const handleReject = value => {
try {
if (typeof onRejected !== "function") {
// 如果onFulfilled不是函数,则直接返回当前promise的value值
resolve(value);
} else {
const res = onRejected(value);
if (res instanceof Promise) {
res.then(resolve, reject);
} else {
resolve(res);
}
}
} catch (err) {
reject(err);
}
};
switch (this._status) {
case this.STATUS.PENDING:
this._fulfilledQueues.push(handleResolve);
this._rejectedQueues.push(handleReject);
break;
case this.STATUS.FULFILLED:
handleResolve(this._value);
break;
case this.STATUS.REJECTED:
handleReject(this._value);
break;
}
});
}
catch(onRejected) {
return this.then(null, onRejected);
}
// 添加静态resolve方法
static resolve(value) {
// 如果参数是MyPromise实例,直接返回这个实例
if (value instanceof Promise) return value;
return new Promise(resolve => resolve(value));
}
// 添加静态reject方法
static reject(err) {
return new Promise((resolve, reject) => reject(err));
}
// 添加静态all方法,所有promise入参状态发生改变后才改变状态
static all(list) {
return new Promise((resolve, reject) => {
const length = list.length;
let count = 0;
let values = [];
// // entries返回数组的键值对[[index, value]...]
// for (let [i, p] of list.entries()) {
//
// }
for (let i = 0; i < length; i++) {
const promise = list[i];
promise.then(
res => {
// promise有可能异步执行resolve,不能用push
values[i] = res;
count++;
if (count === length) {
resolve(values);
}
},
err => {
// 只要子元素promise中有任何一个reject,则返回的promise rejected
reject(err);
}
);
}
});
}
// 添加静态race方法
static race(list) {
return new Promise((resolve, reject) => {
for (let p of list) {
// 只要有一个实例率先改变状态,新的MyPromise的状态就跟着改变
this.resolve(p).then(
res => {
resolve(res);
},
err => {
reject(err);
}
);
}
});
}
/*finally() 方法返回一个Promise。
在promise结束时,无论结果是fulfilled或者是rejected,都会执行指定的回调函数。
这为在Promise是否成功完成后都需要执行的代码提供了一种方式。
这避免了同样的语句需要在then()和catch()中各写一次的情况。*/
finally(handle) {
return this.then(
value => {
handle();
return Promise.resolve(value);
},
err => {
handle();
return Promise.reject(err);
}
);
}
}
// console.log(Promise.resolve)
// // new Promise((res, rej) => setTimeout(() => rej(777)), 1000)
// // .then(res => console.log({res}), err => console.log(1, err))
// // .then(res => console.log({res}), err => console.log(2, err))
//
// console.log(Promise.resolve(Promise.resolve(222)))
//
//
// // new Promise((res, rej) => rej(666))
// // .then(res => console.log({res}), err => new Promise(res => setTimeout(() => res (123),3000)))
// // .then(res => console.log({then2: res}), err => console.log(2, err))
//
// new Promise((res, rej) => res(new Promise((r, err) => err(857))))
// .then(null, e => new Promise(res => res(111)))
// .then(a => console.log({a})).catch(cat => console.log({cat}))
console.log("哇哈哈");
setTimeout(() => {
console.log("setTimeout");
}, 0);
new Promise((res, rej) => {
rej(111);
})
.finally(() => {
console.log("执行finally");
})
.then(null, err => console.log({ err }));
console.log("666");
if (window) {
console.log("you dinwow");
}
以上是关于javascript Promise底层实现的主要内容,如果未能解决你的问题,请参考以下文章