promise.pptx
/*
* 基于Promise/A+规范实现 Promise https://promisesaplus.com/
*/
const PENDING = "pending";
const FULFILLED = "fulfilled";
const REJECTED = "rejected";
class MyPromise {
constructor(fn) {
this.status = PENDING;
this.value = "";
this.onResolvedCallbacks = [];
this.onRejectedCallbacks = [];
try {
fn(this.resolve.bind(this), this.reject.bind(this));
} catch (e) {
this.reject.bind(this, e);
}
}
resolve(value) {
if (value instanceof Promise) {
return value.then(this.resolve.bind(this), this.reject.bind(this));
}
setTimeout(() => {
if (this.status === PENDING) {
this.status = FULFILLED;
this.value = value;
this.onResolvedCallbacks.map(fn => fn(this.value));
}
});
}
reject(err) {
setTimeout(() => {
if (this.status === PENDING) {
this.status = REJECTED;
this.value = err;
this.onRejectedCallbacks.map(fn => fn(this.value));
}
});
}
then(onFulfilled, onRejected) {
let that = this;
onFulfilled =
typeof onFulfilled === "function" ? onFulfilled : value => value;
onRejected =
typeof onRejected === "function"
? onRejected
: err => {
throw err;
};
let promise2;
if (this.status === FULFILLED) {
promise2 = new MyPromise(function(resolve, reject) {
setTimeout(() => {
try {
let x = onFulfilled(that.value);
resolvePromise(promise2, x, resolve, reject);
} catch (e) {
reject(e);
}
});
});
}
if (this.status === REJECTED) {
return new MyPromise(function(resolve, reject) {
setTimeout(() => {
try {
let x = onRejected(that.value);
resolvePromise(promise2, x, resolve, reject);
} catch (e) {
reject(e);
}
});
});
}
if (this.status === PENDING) {
promise2 = new MyPromise(function(resolve, reject) {
that.onResolvedCallbacks.push(function(value) {
try {
let x = onFulfilled(value);
resolvePromise(promise2, x, resolve, reject);
} catch (e) {
reject(e);
}
});
that.onRejectedCallbacks.push(function(value) {
try {
let x = onRejected(value);
resolvePromise(promise2, x, resolve, reject);
} catch (e) {
reject(e);
}
});
});
}
return promise2;
}
catch(obRejected) {
return this.then(null, onRejected);
}
}
function resolvePromise(promise2, x, resolve, reject) {
let then, called;
if (x !== null && (typeof x === "object" || typeof x === "function")) {
try {
then = x.then;
if (typeof then === "function") {
then.call(
x,
function(y) {
if (called) return;
called = true;
resolvePromise(promise2, y, resolve, reject);
},
function(r) {
if (called) return;
called = true;
reject(r);
}
);
} else {
resolve(x);
}
} catch (e) {
if (called) return;
called = true;
reject(e);
}
} else {
resolve(x);
}
}
module.exports = MyPromise;