Promise介绍
1、本质:Promise本质上是构造函数。
Promise的构造函数接收一个参数,是函数,并且传入两个参数:resolve,reject,分别表示异步操作执行状态为fullfiled后的回调函数和异步操作执行状态为rejected后的回调函数。
2、作用:可以根据一个异步操作的最终结果(可以理解为成功或失败)执行不同的回调方法。可以解决之前异步回调地狱的问题。
3、使用:
//定义一个promise
let syncExample = new Promise(function(resolve, reject){
let nowDate = new Date().getDay();
if (nowDate > 3){ //3号以后
resolve(nowDate);
} else {
reject(nowDate)
}
});
//应用
syncExample.then(function (res) {
//3号以后的回调
},function (reason) {
//3号之前的回调
//和下面的catch一样,只不过报错之后会直接进入catch,一般写一个catch就可以,这样就算是报错之后也不会卡死。
}).catch(function (reason) {
//3号之前的回调
//和上面的第二个函数参数 一样,只不过报错之后会直接进入catch
})
手写Promise
上面我们了解了Promise的概念,知道了基本的使用方法以及其用途。现在可以尝试手动“还原”一下Promise的真面目。
大体思路:
1、声明一个构造函数Promise,然后构造函数的参数是一个回调函数parent,这个函数的主要作用是根据不同的状态执行不同的代码,通过上面的示例可以知道,“根据不同状态执行不同的代码”已经被封装成了两个不同的回调函数child,作为回调函数parent的两个参数
2、Promise有原生的then、all等方法,直接挂载到原型链上即可
3、Promise的回调函数child还有可能返回一个Promise,也就是链式调用。这就需要我们再then方法中进行处理:根据不同状态执行对应回调的时候,需要返回一个Promise来包裹住回调。也就说实例promise1,,执行完返回一个promise2,promise2还有可能返回一个promise3,直到返回的是一个普通值。
function Promise (executor) {
//从上面的使用示例可以看到在new Promise的时候传入了一个函数,这里我们将参数命名为executor
let self = this;
self.status = 'pending' //状态值
self.value = undefined //成功的返回值
self.reason = undefined //失败的返回值
self.onResolvedCallbacks = [] //成功的回调函数
self.onRejectedCallbacks = [] //失败的回调函数
function resolve (value) {
self.status = 'fullfiled';
self.value = value;
self.onResolvedCallbacks.forEach (fun) {
fun();
}
}
function reject(reson) {
self.status = 'rejected';
self.reason = reason;
self.onRejectedCallbacks.forEach (fun) {
fun();
}
}
try {
executor(resolve ,reject)
} catch (error) {
reject(error)
}
}
Promise.prototype.then = function (onFullFilled, onRejected){
let self = this;
// 如果then的参数不是function,则我们需要忽略它
onFullFilled= typeof onFullFilled=== 'function' ? onFullFilled: function(value) {}
onRejected= typeof onRejected=== 'function' ? onRejected: function(reason) {}
if (self.status === 'fullfiled') {
onFullFilled(this.value)
}
if (self.status === 'rejected') {
onRejected(this.reason);
}
if (self.status == 'pending') {
self.onResolvedCallbacks.push(function (){
onFullFilled(this.value)
})
this.onRejectedCallbacks.push(function (){
onRejected(this.reason)
})
}
};
Promise.prototype.catch = function(onRejected){
return this.then(undefined, onReJected)
};
//其他的all、race等方法暂且不写
基本上第一步就完成了,但是还差很重要的一个环节,就是链式调用。其实就是在每次返回的时候再包一层Promise。
完整代码:
function Promise (executor) {
let self = this;
//从上面的使用示例可以看到在new Promise的时候传入了一个函数,这里我们将参数命名为executor
self.status = 'pending' //状态值
self.value = undefined //成功的返回值
self.reason = undefined //失败的返回值
self.onResolvedCallbacks = [] //成功的回调函数
self.onRejectedCallbacks = [] //失败的回调函数
function resolve (value) {
self.status = 'fullfiled';
self.value = value;
self.onResolvedCallbacks.forEach (fun) {
fun();
}
}
function reject(reson) {
self.status = 'rejected';
self.reason = reason;
self.onRejectedCallbacks.forEach (fun) {
fun();
}
}
try {
executor(resolve ,reject)
} catch (error) {
reject(error)
}
}
Promise.prototype.then = function (onFullFilled, onRejected){
let self = this;
// 如果then的参数不是function,则我们需要忽略它
onFullFilled= typeof onFullFilled=== 'function' ? onFullFilled: function(value) {}
onRejected= typeof onRejected=== 'function' ? onRejected: function(reason) {}
if (self.status === 'fullfiled') {
return new Promise(function (resloved,rejected) {
try {
let x= onFullFilled(self.value);
if (x instanceof Promise) {
x.then(onFullFilled, onRejected)
} else {
onFullFilled(x)
}
} catch (error) {
onRejected(error)
}
})
}
if (self.status === 'rejected') {
return new Promise(function (resloved,rejected) {
try {
let x= onRejected(self.value);
if (x instanceof Promise) {
x.then(onFullFilled, onRejected)
} else {
onRejected(x)
}
} catch (error) {
onRejected(error)
}
})
}
if (self.status == 'pending') {
return new Promise((resolve, reject) => {
self.onResolvedCallbacks.push(() => {
let x = onFulfilled(self.value);
x instanceof Promise ? x.then(resolve, reject) : resolve(x);
});
self.onRejectedCallbacks.push(() => {
let x = onRejected(self.reason);
x instanceof Promise ? x.then(resolve, reject) : resolve(x);
});
});
}
};
Promise.prototype.catch = function(onRejected){
return this.then(undefined, onReJected)
};
//其他的all、race方法暂且不写