Promise 对象用于表示一个异步操作的最终状态(完成或失败),以及其返回的值。
Promise 对象是一个代理对象(代理一个值),被代理的值在Promise对象创建时可能是未知的。它允许你为异步操作的成功和失败分别绑定相应的处理方法(handlers)。 这让异步方法可以像同步方法那样返回值,但并不是立即返回最终执行结果,而是一个能代表未来出现的结果的promise对象
一个 Promise有以下几种状态:
- pending: 初始状态,既不是成功,也不是失败状态。
- fulfilled: 意味着操作成功完成。
- rejected: 意味着操作失败。
pending 状态的 Promise 对象可能触发fulfilled状态并传递一个值给相应的状态处理方法,也可能触发失败状态(rejected)并传递失败信息。当其中任一种情况出现时,Promise 对象的 then 方法绑定的处理方法(handlers )就会被调用(then方法包含两个参数:onfulfilled 和onrejected,它们都是 Function 类型。当Promise状态为fulfilled时,调用 then 的onfulfilled 方法,当Promise状态为rejected时,调用 then 的 onrejected 方法, 所以在异步操作的完成和绑定处理方法之间不存在竞争)。
实现如下:
// 实现Promise
function Promise(executor){
let self = this;
// 保存初始化的状态
self.status = 'pedding';
// 接收成功的值
self.value = undefined;
// 接收失败的原因
self.reason = undefined;
// 存放成功的回调
self.onResolved = [];
// 存放失败的回调
self.onRejected = [];
function resolve(value) {
if (self.status === 'pedding') {
// 将成功的值保存起来
self.value = value;
// 成功时改变为成功状态
self.status = 'fulfilled';
self.onResolved.forEach(fn => fn());
}
}
function reject(reason) {
if (self.status === 'pedding') {
// 将失败的原因存起来
self.reason = reason;
// 失败时改变为失败状态
self.status = 'rejected';
self.onRejected.forEach(fn => fn());
}
}
// 处理异常
try {
executor(resolve, reject);
}catch(e) {
reject(e);
}
// (resolve, reject)();
}
Promise.prototype.then = function (onfulfilled, onrejected) {
// 判断是否有相应的回调函数
// 如果没有成功时的回调默认返回值
// 如果没有失败时的回调默认抛出异常
onfulfilled = typeof onfulfilled == 'function' ? onfulfilled : val => val;
onrejected = typeof onrejected == 'function' ? onrejected : err => {
throw err;
};
let self = this,
promise2;
// 实现链式调用
return promise2 = new Promise((resolve, reject) => {
// 成功时调用成功的回调
if (self.status === 'fulfilled') {
let res = onfulfilled(self.value);
resolvePromise(promise2, res, resolve, reject);
// onfulfilled(self.value);
}
// 失败时调用失败的回调
if (self.status === 'rejected') {
let res = onrejected(self.reason);
resolvePromise(promise2, res, resolve, reject);
// onrejected(self.reason);
}
// pedding时把成功和失败的回调存入数组中
if (self.status === 'pedding') {
self.onResolved.push(function() {
// onfulfilled(self.value);
let res = onfulfilled(self.value);
resolvePromise(promise2, res, resolve, reject);
});
self.onRejected.push(function() {
// onrejected(self.reason);
let res = onrejected(self.reason);
resolvePromise(promise2, res, resolve, reject);
});
}
})
}
// 扩展catch方法
Promise.prototype.catch = function (onrejected) {
return this.then(null, onrejected)
}
// 扩展reject方法
Promise.reject = function (reason) {
return new Promise((resolve, reject) => {
reject(reason)
})
}
// 扩展resolve方法
Promise.resolve = function (value) {
return new Promise((resolve, reject) => {
resolve(value);
})
}
// 解决回调地狱 处理链式调用问题
function resolvePromise(p2, x, resolve, reject) {
if(p2 === x){
ject(new TypeError('循环引用'));
}
if(x!= null && (typeof x === 'object' || typeof x === 'function')){
try{
let then = x.then;
if(typeof then === 'function'){
then.call(x, (y) => {
if (called) return;
called = true;
resolvePromise(promise2, y, resolve, reject);
}, (err) => {
if (called) return ;
called = true;
reject(err);
});
}else{
resolve(x);
}
}catch(e){
reject(e);
}
}else{
resolve(x);
}
}
运行测试代码如下
let promise = new Promise((resolve,reject)=>{
resolve(1);
});
console.log('start');
promise.then((value) => {
console.log(value)
return value;
}, (reason) => {
console.log(reason);
})
.then((data) => {
console.log("data"+ data);
});
console.log('end');
运行结果如下