class Promise {
constructor(executor) {
this.status = 'pending';
this.value = null;
this.reason = null;
this.onResolveCb = [];
this.onRejectCb = [];
const resolve = (val) => {
if (this.status !== 'pending') return;
this.status = 'fulfilled';
this.value = val;
this.onResolveCb.forEach(fn => fn());
};
const reject = (err) => {
if (this.status !== 'pending') return;
this.status = 'rejected';
this.reason = err;
this.onRejectCb.forEach(fn => fn());
};
try {
executor(resolve, reject);
} catch (e) {
reject(e);
}
}
then(onResolve, onReject) {
onResolve = onResolve || (v => v);
onReject = onReject || (e => { throw e; });
return new Promise((resolve, reject) => {
if (this.status === 'fulfilled') {
setTimeout(() => resolve(onResolve(this.value)));
}
else if (this.status === 'rejected') {
setTimeout(() => reject(onReject(this.reason)));
}
else {
this.onResolveCb.push(() => {
setTimeout(() => resolve(onResolve(this.value)));
});
this.onRejectCb.push(() => {
setTimeout(() => reject(onReject(this.reason)));
});
}
});
}
catch(fn) {
return this.then(null, fn);
}
}