const PENDING = "pending";
const REJECTED = "rejected";
const FULFILLED = "fulfilled";
function isFunction(func) {
return typeof func === "function";
}
function isObject(obj) {
return typeof obj === "object" && obj !== null;
}
function resolutionProcedure(promise, x, resolve, reject) {
if (promise === x) {
reject(new TypeError("promise and x refer to the same object"));
return;
}
if (isObject(x) || isFunction(x)) {
try {
let then = x.then;
if (isFunction(then)) {
let isCalled = false;
try {
then.call(
x,
(y) => {
if (isCalled) {
return;
}
isCalled = true;
resolutionProcedure(promise, y, resolve, reject);
},
(r) => {
if (isCalled) {
return;
}
isCalled = true;
reject(r);
}
);
} catch (error) {
if (isCalled) {
return;
}
isCalled = true;
reject(error);
}
} else {
resolve(x);
}
} catch (error) {
reject(error);
}
} else {
resolve(x);
}
}
class PromiseA {
constructor(expression) {
this.PromiseState = PENDING;
this.PromiseResult = undefined;
this.onFulfilledCallbacks = [];
this.onRejectedCallbacks = [];
let resolve = (value) => {
if (this.PromiseState === PENDING) {
this.PromiseState = FULFILLED;
this.PromiseResult = value;
this.onFulfilledCallbacks.forEach((cb) => {
cb();
});
}
};
let reject = (reason) => {
if (this.PromiseState === PENDING) {
this.PromiseState = REJECTED;
this.PromiseResult = reason;
this.onRejectedCallbacks.forEach((cb) => {
cb();
});
}
};
expression(resolve, reject);
}
then(onFulfilled, onRejected) {
let x;
// let [onFulfilled, onRejected] = Array.prototype.slice.call(arguments);
if (!isFunction(onFulfilled)) {
onFulfilled = (data) => {
return data;
};
}
if (!isFunction(onRejected)) {
onRejected = (error) => {
throw error;
};
}
let promise2 = new PromiseA((resolve, reject) => {
if (this.PromiseState === PENDING) {
this.onFulfilledCallbacks.push(() => {
setTimeout(() => {
try {
x = onFulfilled(this.PromiseResult);
resolutionProcedure(promise2, x, resolve, reject);
} catch (e) {
reject(e);
}
});
});
this.onRejectedCallbacks.push(() => {
setTimeout(() => {
try {
x = onRejected(this.PromiseResult);
resolutionProcedure(promise2, x, resolve, reject);
} catch (e) {
reject(e);
}
});
});
}
if (this.PromiseState === FULFILLED) {
setTimeout(() => {
try {
x = onFulfilled(this.PromiseResult);
resolutionProcedure(promise2, x, resolve, reject);
} catch (e) {
reject(e);
}
});
}
if (this.PromiseState === REJECTED) {
setTimeout(() => {
try {
x = onRejected(this.PromiseResult);
resolutionProcedure(promise2, x, resolve, reject);
} catch (e) {
reject(e);
}
});
}
});
return promise2;
}
catch() {
}
finally() {
}
}
代码测试:
let p2 = new PromiseA(function (resolve, reject) {
console.log(2);
setTimeout(() => {
reject("failed");
}, 2000);
});
console.log(3);
p2.then(
(data) => {
console.log("data");
console.log(data);
},
(error) => {
console.log(4);
console.log(error);
}
).then(
(data) => {
console.log("data");
console.log(data);
},
(error) => {
console.log(4);
console.log(error);
}
);
p2.then(
(data) => {
console.log(6);
console.log(data);
},
(error) => {
console.log(4);
console.log(error);
}
);
console.log(5);
PromiseA.defer = PromiseA.deferred = function () {
let dfd = {
};
dfd.promise = new PromiseA((resolve, reject) => {
dfd.resolve = resolve;
dfd.reject = reject;
});
return dfd;
};