Promise/A+规范中文翻译:http://www.ituring.com.cn/article/66566
Promise
- Promise 是异步编程的一种解决方案,比传统的解决方案——回调函数和事件——更合理和更强大
Promise 的三种状态
- Pending Promise对象实例创建时候的初始状态
- Fulfilled 可以理解为成功的状态
- Rejected 可以理解为失败的状态
使用 Promise
const promise = new Promise(function(resolve, reject) {
// ... some code
if (/* 异步操作成功 */){
resolve(value);
} else {
reject(error);
}
});
promise.then(function(value) {
// success
}, function(error) {
// failure
});
根据Promise/A+规范实现一个 Promise
/**
* @file myPromise
* @author: wuchangdong
*/
function Promise(task) {
let that = this; // 缓存this
that.status = 'pending'; // 默认状态
that.value = undefined; // 返回的值
that.onResolvedCallbacks = []; // 存放所有成功的回调函数
that.onRejectdCallbacks = []; // 存放所有失败的回调函数
// 调用此方法可以把promise变成成功态
function resolve(value) {
if (that.status === 'pending') {
that.status = 'fulfilled';
that.value = value;
that.onResolvedCallbacks.forEach(item => item(that.value));
}
}
// 调用此方法可以把当前的promise变成失败态
function reject(reason) {
if (that.status === 'pending') {
that.status = 'rejected';
that.value = reason;
that.onResolvedCallbacks.forEach(item => item(that.value));
}
}
// 立即执行传入的任务
try {
task(resolve, reject);
}
catch (e) {
reject(e);
}
}
// 兼容其他 Promise
function resolvePromise(promise2, x, resolve, reject) {
let then;
// 如果x就是promise2
if (promise2 === x) {
return reject(new TypeError('循环引用'));
}
if (x instanceof Promise) {
if (x.status === 'pending') {
x.then(function (y) {
resolvePromise(promise2, y, resolve, reject);
},
reject);
}
else if (x.status === 'fulfilled') {
resolve(x.value);
}
else if (x.status === 'rejected') {
reject(x.value);
}
}
else if (x !== null && (typeof x === 'object' || typeof x === 'function')) {
try {
then = x.then;
if (typeof then === 'function') {
then.call(x, function (y) {
resolvePromise(promise2, y, resolve, reject);
},
reject);
}
}
catch (e) {
reject(e);
}
}
else {
resolve(x);
}
}
// onFulfilled成功的回调,onReject失败的回调
Promise.prototype.then = function (onFulfilled, onReject) {
onFulfilled = typeof onFulfilled === 'function'
? onFulfilled
: function (value) {
return value;
};
onReject = typeof onReject === 'function'
? onReject
: function (reason) {
throw reason;
};
let that = this;
let promise2;
if (that.status === 'fulfilled') {
promise2 = new Promise(function (resolve, reject) {
setTimeout(function () {
try {
let x = onFulfilled(self.value);
resolvePromise(promise2, x, resolve, reject);
}
catch (e) {
reject(e);
}
}, 0);
});
}
if (that.status === 'rejected') {
promise2 = new Promise(function (resolve, reject) {
setTimeout(function () {
try {
let x = onReject(self.value);
resolvePromise(promise2, x, resolve, reject);
}
catch (e) {
reject(e);
}
}, 0);
});
}
if (that.status === 'pending') {
promise2 = new Promise(function (resolve, reject) {
that.onResolvedCallbacks.push(function () {
let x = onFulfilled(that.value);
resolvePromise(promise2, x, resolve, reject);
});
that.onRejectdCallbacks.push(function () {
let x = onFulfilled(that.value);
resolvePromise(promise2, x, resolve, reject);
});
});
}
return promise2;
};
module.exports = Promise;