const PENDING = "pending";
const FULFILLED = "fulfilled";
const REJECTED = "rejected";
function runMicroqueue(callback) {
if (process.nextTick) {
process.nextTick(callback);
} else if (MutationObserver) {
let p = document.createElement('p');
let observe = new MutationObserver(callback);
observe.observe(p, {
subtree: true,
childList: true
});
p.innerHTML = '1';
} else {
setTimeout(callback, 0);
}
}
function isPromise(obj) {
return !!(obj && typeof obj === 'object' && typeof obj.then === 'function')
}
class MyPromise {
constructor(execution) {
this._value = undefined;
this._state = PENDING;
this._handles = [];
try {
execution(this._resolve.bind(this), this._reject.bind(this));
} catch (err) {
this._reject(err);
}
}
_changeValueAndState(value, state) {
if (this._state !== PENDING) return;
this._value = value;
this._state = state;
this._runHandles();
}
_resolve(data) {
this._changeValueAndState(data, FULFILLED);
}
_reject(reason) {
this._changeValueAndState(reason, REJECTED);
}
_pushHandles(callback, state, resolve, reject) {
this._handles.push({
callback,
state,
resolve,
reject
});
}
_runHandles() {
if (this._state === PENDING) return;
while (this._handles[0]) {
this._runHandle(this._handles[0]);
this._handles.shift();
}
}
_runHandle({
callback,
state,
resolve,
reject
}) {
runMicroqueue(() => {
if (this._state !== state) return;
if (typeof callback !== "function") {
this._state === FULFILLED ? resolve(this._value) : reject(this._value);
}
try {
let result = callback(this._value);
isPromise(result) ? result.then(resolve, reject) : resolve(result);
} catch (err) {
reject(err);
}
})
}
then(onFulfilledFun, onRejectedFun) {
return new MyPromise((resolve, reject) => {
this._pushHandles(onFulfilledFun, FULFILLED, resolve, reject);
this._pushHandles(onRejectedFun, REJECTED, resolve, reject);
this._runHandles();
})
}
}
let pro = new Promise((resolve, reject) => {
resolve(1);
})
pro.then((data) => {
console.log(data);
return new MyPromise((resolve, reject) => {
resolve("返回");
})
}, (err) => {
console.log(err);
}).then((data) => {
console.log(data);
}, (err) => {
console.log(err);
})