实现 Promise/A+ 规范
// 三种状态
var status = {
pending: 'pending',
fulFilled: 'fulFilled',
rejected: 'rejected',
}
function Promise(exector) {
// 当前状态
this.status = status.pending;
// fulFilled状态的值
this.value = undefined;
// rejected状态的值
this.reason = null;
// fulFilled状态的回调函数
this.onFulfilledHandlers = [];
// rejected状态的回调函数
this.onRejectedHandlers = [];
const self = this;
// 状态从pending变为fulFilled
function resolve(value) {
if (value instanceof Promise) {
return value.then(resolve, reject);
}
if (self.status === status.pending) {
self.status = status.fulFilled;
self.value = value;
setTimeout(function () {
self.onFulfilledHandlers.forEach(function (h) {
h(self.value);
});
});
}
}
// 状态从pending变为rejected
function reject(reason) {
if (self.status === status.pending) {
self.status = status.rejected;
self.reason = reason;
setTimeout(function () {
self.onRejectedHandlers.forEach(function (h) {
h(self.reason);
});
});
}
}
// exector执行时可能会抛异常
// 如果不捕获,异常会抛到全局
try {
exector(resolve, reject);
} catch (e) {
reject(e);
}
}
// then方法
Promise.prototype.then = function (onFulfilled, onRejected) {
// 如果onFulfilled不是函数,则转为函数
if (typeof onFulfilled !== 'function') {
onFulfilled = function (value) {
return value;
}
}
// 如果onFulfilled不是函数,则转为函数
if (typeof onRejected !== 'function') {
onRejected = function (reason) {
throw reason;
}
}
const self = this;
// then返回一个promise
let promise2 = null;
// onFulfilled或onRejected的返回值
let x = undefined;
// 如果已经是fulFilled状态
if (this.status === status.fulFilled) {
promise2 = new Promise(function (resolve, reject) {
setTimeout(function () {
try {
x = onFulfilled(self.value);
resolvePromise(promise2, x, resolve, reject);
} catch (e) {
reject(e);
}
});
});
}
// 如果已经是rejected状态
if (this.status === status.rejected) {
promise2 = new Promise(function (resolve, reject) {
setTimeout(function () {
try {
x = onRejected(self.reason);
resolvePromise(promise2, x, resolve, reject);
} catch (e) {
reject(e);
}
});
});
}
// 如果是pending状态
if (this.status === status.pending) {
promise2 = new Promise(function (resolve, reject) {
self.onFulfilledHandlers.push(function (value) {
try {
x = onFulfilled(value);
resolvePromise(promise2, x, resolve, reject);
} catch (e) {
reject(e);
}
});
self.onRejectedHandlers.push(function (reason) {
try {
x = onRejected(reason);
resolvePromise(promise2, x, resolve, reject);
} catch (e) {
reject(e);
}
});
});
}
return promise2;
}
function resolvePromise(promise2, x, resolve, reject) {
if (promise2 === x) {
return reject(new TypeError('circular reference'));
}
let then = null;
let called = false;
if (x instanceof Promise) {
if (x.status === status.rejected) {
reject(x.reason);
} else {
x.then(function (y) {
resolvePromise(promise2, y, resolve, reject);
}, reject);
}
} else 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);
}
}
Promise.deferred = Promise.defer = function () {
var defer = {};
defer.promise = new Promise(function (resolve, reject) {
defer.resolve = resolve;
defer.reject = reject;
})
return defer;
}
module.exports = Promise;
检测通过
promises-aplus-tests Promise.js
实现 ES6 Promise 方法
Promise.prototype.catch = function (reject) {
this.then(null, reject);
}
Promise.all = function (promises) {
return new Promise(function (resove, reject) {
const result = [];
const len = promises.length;
const count = 0;
for (var i = 0; i < len; i++) {
promises[i].then(function (data) {
result[i] = data;
if (++count === len) {
resolve(result);
}
}, function (error) {
reject(error);
});
}
});
}
Promise.race = function (promises) {
return Promise(function (resolve, reject) {
var len = promises.length;
for (var i=0; i < len; i++) {
promises[i].then(resolve, reject);
}
});
}
Promise.resolve = function (value) {
if (value instanceof Promise) return value
return new Promise(function (resolve) {
resolve(value)
});
}
Promise.reject = function (value) {
return new Promise(function (resolve, reject) {
return reject(value);
});
}