# 符合Promise A+规范的实现
// Promise的三种状态
const PENDING = 'PENDING';
const FULFILLED = 'FULFILLED';
const REJECTED = 'REJECTED';
/**
* 用于处理返回新Promise情况的递归,一直深入调用。
* 直到返回不带then函数类型属性的value,传递给startPromise
*/
const resolvePromise = (startPromise, x, resolve, reject) => {
if (startPromise === x) {
return reject(new TypeError('Chaining cycle detected for promise #<Promise>'));
}
let called;
if ((typeof x === 'object' && x != null) || typeof x === 'function') {
try {
let then = x.then;
if (typeof then === 'function') {
then.call(x, y => {
if (called) return;
called = true;
resolvePromise(startPromise, y, resolve, reject);
}, r => {
if (called) return;
called = true;
reject(r);
});
} else {
if (called) return;
called = true;
resolve(x);
}
} catch (error) {
if (called) return;
called = true;
reject(error);
}
} else {
resolve(x);
}
};
class Promise {
constructor(executor) {
this.status = PENDING;
this.value = undefined;
this.reason = undefined;
this.onResolvedCallbacks = [];
this.onRejectedCallbacks = [];
let resolve = (value) => {
if (value instanceof Promise) {
return value.then(resolve, reject);
}
if (this.status === PENDING) {
this.status = FULFILLED;
this.value = value;
this.onResolvedCallbacks.forEach(fn => fn());
}
}
let reject = (reason) => {
if (this.status === PENDING) {
this.status = REJECTED;
this.reason = reason;
this.onRejectedCallbacks.forEach(fn => fn());
}
}
try {
executor(resolve, reject);
} catch(err) {
reject(err);
}
}
then(onFulfilled, onRejected) {
onFulfilled = typeof onFulfilled === 'function' ? onFulfilled : v => v;
onRejected = typeof onRejected === 'function' ? onRejected : err => {throw err};
let chainPromise = new Promise((resolve, reject) => {
if (this.status === FULFILLED) {
setTimeout(() => {
try {
let x = onFulfilled(this.value);
resolvePromise(chainPromise, x, resolve, reject);
} catch (e) {
reject(e);
}
}, 0);
}
if (this.status === REJECTED) {
setTimeout(() => {
try {
let x = onRejected(this.reason);
resolvePromise(chainPromise, x, resolve, reject);
} catch (e) {
reject(e);
}
}, 0);
}
if (this.status === PENDING) {
this.onResolvedCallbacks.push(() => {
setTimeout(() => {
try {
let x = onFulfilled(this.value);
resolvePromise(chainPromise, x, resolve, reject);
} catch (e) {
reject(e);
}
}, 0)
});
this.onRejectedCallbacks.push(() => {
setTimeout(() => {
try {
let x = onRejected(this.reason);
resolvePromise(chainPromise, x, resolve, reject);
} catch (e) {
reject(e);
}
}, 0);
});
}
});
return chainPromise;
}
static resolve(value) {
return new Promise((resolve) => {
resolve(value);
});
}
static reject(reason) {
return new Promise((_resolve, reject) => {
reject(reason);
});
}
catch(errCallback) {
return this.then(null, errCallback);
}
finally(callback) {
return this.then((value) => {
return Promise.resolve(callback()).then(() => value);
}, (reason) => {
return Promise.reject(callback()).then(() => {throw reason});
});
}
static all(values) {
return new Promise((resolve, reject) => {
let resultArr = [];
let orderIndex = 0;
const processResultByKey = (value, index) => {
resultArr[index] = value;
if (++orderIndex === values.length) {
resolve(resultArr);
}
};
for (let i = 0; i < values.length; i++) {
let value = values[i];
if (value && typeof value.then === 'function') {
value.then((value) => {
processResultByKey(value, i);
}, reject);
} else {
processResultByKey(value, i);
}
}
});
}
static race(values) {
return new Promise((resolve, reject) => {
for (let i = 0; i < values.length; i++) {
let value = values[i];
if (value && typeof value.then === 'function') {
value.then(resolve, reject);
} else {
resolve(value);
}
}
});
}
}
// 添加该方法可使用promises-aplus-tests模块测试Promise方法是否符合Promise A+规范
Promise.defer = Promise.deferred = function () {
let dfd = {};
dfd.promise = new Promise((resolve, reject) => {
dfd.resolve = resolve;
dfd.reject = reject;
});
return dfd;
}
module.exports = Promise;