// 定义三种状态、resolve和reject方法、then方法(onFulfilled、onRejected)
// 支持异步resolve.
function myPromise(constructor) {
this.status = "pending" //定义初始状态
this.value = undefined;//存储成功后的值
this.reason = undefined;//存储失败的原因
// 成功存放的数组
this.onResolvedCallbacks = [];
// 失败存放法数组
this.onRejectedCallbacks = [];
let resolve = value => {
if (this.status === "pending") {
console.log(1)
this.status = "resolved";
this.value = value;
// 一旦resolve执行,调用成功数组的函数
this.onResolvedCallbacks.forEach(fn => fn());
console.log(2)
}
}
let reject = reason => {
if (this.status === "pending") {
this.status = "rejected";
this.reason = reason;
// 一旦reject执行,调用失败数组的函数
this.onRejectedCallbacks.forEach(fn => fn());
}
}
//捕获构造异常
try {
constructor(resolve, reject);
} catch (e) {
reject(e);
}
}
myPromise.prototype.then = function (onFulfilled, onRejected) {
// 状态为fulfilled,执行onFulfilled,传入成功的值
if (this.status === 'resolved') {
onFulfilled(this.value);
};
// 状态为rejected,执行onRejected,传入失败的原因
if (this.status === 'rejected') {
onRejected(this.reason);
};
// 当状态status为pending时
if (this.status === 'pending') {
// onFulfilled传入到成功数组
this.onResolvedCallbacks.push(() => {
onFulfilled(this.value);
})
// onRejected传入到失败数组
this.onRejectedCallbacks.push(() => {
onRejected(this.reason);
})
}
}
const Status = { PENDING: Symbol('pending'), FUFILLED: Symbol('fulfilled'), REJECTED: Symbol('rejected'), } class MyPromise { constructor(callback) { this.Status = Status.PENDING; this.value = null; this.array = []; try { callback(this.resolve.bind(this), this.reject.bind(this)); } catch (error) { this.reject(error); } } resolve(value) { if (this.Status === Status.PENDING) { this.Status = Status.FUFILLED; this.value = value; setTimeout(() => { this.array.forEach(item => { item.onFulfilled(value); }); }); } } reject(reason) { if (this.Status === Status.PENDING) { this.Status = Status.REJECTED; this.value = reason; setTimeout(() => { this.array.forEach(item => { item.onRejected(reason); }); }); } } then(onFulfilled, onRejected) { if (typeof onFulfilled !== 'function') { onFulfilled = () => this.value } if (typeof onRejected !== 'function') { onRejected = (err) => { throw err } } const promise = new MyPromise((resolve, reject) => { if (this.Status === Status.PENDING) { this.array.push({ onFulfilled: (value) => { const result = onFulfilled(value); resolve(result); }, onRejected: (reason) => { const result = onRejected(reason); resolve(result); } }); } if (this.Status === Status.FUFILLED) { setTimeout(() => { try { const result = onFulfilled(this.value); resolve(result); } catch (error) { reject(error); } }); } if (this.Status === Status.REJECTED) { setTimeout(() => { try { const result = onRejected(this.value); resolve(result); } catch (error) { reject(error); } }); } }); return promise; } catch(onRejected) { return this.then(null, onRejected) } finally(callback) { const MyPromise = this.constructor; return this.then( value => MyPromise.resolve(callback()).then(() => value), reason => MyPromise.resolve(callback()).then(() => { throw reason }) ); } static resolve(promise) { return new MyPromise((resolve, reject) => { if (promise instanceof MyPromise) { promise.then(resolve); } else { resolve(promise); } }); } static reject(promise) { return new MyPromise((resolve, reject) => { reject(promise); }); } static all(promises) { const values = []; return new MyPromise((resolve, reject) => { promises.forEach(promise => { promise.then(value => { values.push(value); if (values.length === promises.length) { resolve(values); } }, reason => { reject(reason); }); }); }); } }
const isFunction = variable => typeof variable === "function";
const __ = new WeakMap();
function get(that, key) {
try {
return __.get(that)[key];
} catch (e) {
console.error(e);
return undefined;
}
}
function set(that, key, value) {
const lastValue = __.get(that);
const newValue = {
...lastValue,
[key]: value
};
__.set(that, newValue);
}
const promiseStatus = Symbol("status");
const promiseValue = Symbol("value");
const fulfilledCallbackQueue = Symbol("fulfilledCallbackQueue");
const rejectedCallbackQueue = Symbol("rejectedCallbackQueue");
const PENDING = Symbol("pending");
const FULFILLED = Symbol("fulfilled");
const REJECTED = Symbol("rejected");
const resolve = Symbol("resolve");
const reject = Symbol("reject");
class MyPromise {
constructor(fn) {
if (!isFunction(fn)) {
throw new Error("MyPromise must accept a function as a parameter");
}
set(this, promiseStatus, PENDING);
set(this, promiseValue, undefined);
set(this, fulfilledCallbackQueue, []);
set(this, rejectedCallbackQueue, []);
try {
fn(this[resolve].bind(this), this[reject].bind(this));
} catch (e) {
this[reject](e);
}
}
[resolve](val) {
const run = () => {
if (get(this, promiseStatus) !== PENDING) return;
const runFulfilled = value => {
let cb;
while ((cb = get(this, fulfilledCallbackQueue).shift())) {
cb(value);
}
};
const runRejected = error => {
let cb;
while ((cb = get(this, rejectedCallbackQueue).shift())) {
cb(error);
}
};
if (val instanceof MyPromise) {
val.then(
value => {
set(this, promiseValue, value);
set(this, promiseStatus, FULFILLED);
runFulfilled(value);
},
err => {
set(this, promiseValue, err);
set(this, promiseStatus, REJECTED);
runRejected(err);
}
);
} else {
set(this, promiseValue, val);
set(this, promiseStatus, FULFILLED);
runFulfilled(val);
}
};
setTimeout(run, 0);
}
[reject](err) {
if (get(this, promiseStatus) !== PENDING) return;
const run = () => {
set(this, promiseStatus, REJECTED);
set(this, promiseValue, err);
let cb;
while ((cb = get(this, rejectedCallbackQueue).shift())) {
cb(err);
}
};
setTimeout(run, 0);
}
then(onFulfilled, onRejected) {
return new MyPromise((onFulfilledNext, onRejectedNext) => {
const fulfilled = value => {
try {
if (!isFunction(onFulfilled)) {
onFulfilledNext(value);
} else {
const res = onFulfilled(value);
if (res instanceof MyPromise) {
res.then(onFulfilledNext, onRejectedNext);
} else {
onFulfilledNext(res);
}
}
} catch (err) {
onRejectedNext(err);
}
};
const rejected = error => {
try {
if (!isFunction(onRejected)) {
onRejectedNext(error);
} else {
const res = onRejected(error);
if (res instanceof MyPromise) {
res.then(onFulfilledNext, onRejectedNext);
} else {
onFulfilledNext(res);
}
}
} catch (err) {
onRejectedNext(err);
}
};
switch (get(this, promiseStatus)) {
case PENDING:
const newFulfilledCallbackQueue = [
...get(this, fulfilledCallbackQueue),
fulfilled
];
set(this, fulfilledCallbackQueue, newFulfilledCallbackQueue);
const newRejectedCallbackQueue = [
...get(this, rejectedCallbackQueue),
rejected
];
set(this, rejectedCallbackQueue, newRejectedCallbackQueue);
break;
case FULFILLED:
fulfilled(get(this, promiseValue));
break;
case REJECTED:
rejected(get(this, promiseValue));
break;
}
});
}
}