实现Promise A+大部分规范
const PENDDING = "pendding";
const FULFILLED = "fulfilled";
const REJECTED = "rejected";
/**
* 创造一个微队列
* @param {Function} callback 回调函数
*/
function runMicroMask(callback) {
if (this.MutationObserver) { //浏览器环境
const observer = new MutationObserver(callback);
const div = document.createElement("div");
observer.observe(div, {
childList: true
})
div.innerHTML = "123";
}else if (process && process.nextTick) { //Node环境
process.nextTick(callback);
}else {
setTimeout(callback, 0);
}
}
/**
* 判断传入的值是否是Promise
* @param {any} obj
* @returns
*/
function isPromise(obj) {
return !!(obj && typeof obj === "object" && typeof obj.then === "function")
}
class MyPromise {
/**
* Promise构造器,接收一个立即被执行的函数
* @param {Function} executor
*/
constructor(executor) {
this._state = PENDDING; //promise状态
this._value = undefined; //promise值
this._handlers = []; //then方法的执行队列
try {
executor(this._resolve.bind(this), this._rejected.bind(this));
}catch(error) {
this._rejected(error);
}
}
/**
* 执行队列内容
* @param {Object}
*/
_runHandler({ executor, state, resolve, rejected }) {
runMicroMask(()=> {
if (this._state !== state) return ; //如果当前数据状态与当前promise状态不一致 直接返回
if (typeof executor !== "function") {
state === FULFILLED ? resolve(this._value) : rejected(this._value);
return ;
}
try {
const result = executor(this._value);
if (isPromise(result)) {
result.then(resolve, rejected)
}else {
resolve(result)
}
}catch(error) {
rejected(error);
}
})
}
/**
* 执行队列
*/
_runQueues() {
if (this._state === PENDDING) return ;
while(this._handlers[0]) {
const handler = this._handlers[0];
this._runHandler(handler);
this._handlers.shift();
}
}
/**
* 将未来可能执行的函数放入执行队列
* @param {Function} executor 执行器
* @param {String} state 状态
* @param {Function} resolve 成功回调
* @param {Function} rejected 失败回调
*/
_pushHandlers(executor, state, resolve, rejected) {
this._handlers.push({
executor,
state,
resolve,
rejected
})
}
/**
* Promise的后续处理方法
* @param {Function} onFulfilled 成功时调用
* @param {Function} onRejected 失败时调用
* @returns
*/
then(onFulfilled, onRejected) {
return new MyPromise((resolve, rejected)=> {
this._pushHandlers(onFulfilled, FULFILLED, resolve, rejected);
this._pushHandlers(onRejected, REJECTED, resolve, rejected);
this._runQueues();
})
}
/**
* 失败时调用
* @param {Function} onRejected
*/
catch(onRejected) {
return this.then(null, onRejected);
}
/**
* 无论成功或者失败都会执行
* @param {Function} onSettled
*/
finally(onSettled) {
return this.then(data => {
onSettled();
return data;
},reason => {
onSettled();
return reason;
})
}
/**
* 表示成功
* @param {any} data
*/
static resolve(data) {
if (data instanceof MyPromise) {
return data;
}
return new MyPromise((resolve, reject) => {
if (isPromise(data)) {
data.then(resolve, reject);
}else {
resolve(data);
}
})
}
/**
* 表示失败
* @param {any} reason
*/
static reject(reason) {
return new MyPromise((resolve, reject) => {
reject(reason);
})
}
/**
* 当数组内的promise全部完成时状态为成功,返回所有数据
* 其中一个失败,状态为失败,返回失败原因
* @param {iterator} promises
*/
static all(promises) {
return new MyPromise((resolve, reject) => {
try {
let count = 0;
let resolveCount = 0;
let result = [];
if (promises.length === 0) {
resolve(result);
}
for (const pro of promises) {
let i = count;
count++;
MyPromise.resolve(pro).then(res => {
resolveCount++;
result[i] = res;
if (resolveCount === count) { //表示所有请求都成功了
resolve(result);
}
}, reject)
}
}catch(error) {
reject(error);
}
})
}
/**
* 当所有请求都结束,则返回一个数组对象
* @param {iterator} promises
*/
static allSettled(promises) {
let pro = [];
for (const p of promises) {
pro.push(
MyPromise.resolve(p).then(value => ({
state: FULFILLED,
value
}), reason => ({
state: REJECTED,
reason
}))
)
}
return MyPromise.all(pro)
}
/**
* 竞速,第一个结束的被返回,无论失败或者成功
* @param {iterator} promises
*/
static race(promises) {
return new MyPromise((resolve, reject) => {
for (const p of promises) {
MyPromise.resolve(p).then(resolve, reject)
}
})
}
/**
* 状态和数据改变控制函数
* @param {String} state 改变的状态
* @param {any} value 改变时所附带的值
*/
_change(state, value) {
if (this._state !== PENDDING) return;
this._state = state;
this._value = value;
this._runQueues();
}
/**
* Promise成功时的调用
* @param {any} data 成功时的数据
*/
_resolve(data) {
this._change(FULFILLED, data);
}
/**
* Promise失败时调用
* @param {any} error 错误信息
*/
_rejected(error) {
this._change(REJECTED, error);
}
}