Promise是什么?
Promise是一种异步方法,可以让代码变得简洁,提高代码的阅读性,从而有效的解决回调地狱的问题~
Promise的使用
首先我们要知道,Promise有三种状态,分别是pedding、rejected和resolved,一旦状态发生改变,就不会再变了。
当我们使用Promise时,通过Promise的构造函数new一个实例,它接收一个函数作为参数,这个函数里面有两个参数,分别是resolve和reject,resolve将promise的状态变为成功(resolved),reject将promise的状态变为失败(rejected)
let p = new Promise(function(resolve, reject){
setTimeout(function(){
var num = Math.ceil(Math.random()*20); //生成1-10的随机数
console.log('随机数生成的值:',num)
if(num<=10){
resolve(num); //利用resolve传值
}
else{
reject('数字太于10了即将执行失败回调'); //利用reject传值
}
}, 2000);
})
p.then(function(data){
console.log('resolved成功回调');
console.log('成功回调接受的值:',data);
},
function(reason){
console.log('rejected失败回调');
console.log('失败执行回调抛出失败原因:',reason);
})
实例创建完成后,可以使用then方法分别指定成功或失败的回调函数,也可以使用catch捕获失败,then和catch最终返回的也是一个Promise,所以可以链式调用。
Promise的其他方法
- Promise.reject()创建一个状态为失败的promise对象
- Promise.resolve()创建一个状态为成功的promise对象
- Promise.all([数组])传入的参数是一个数组,数组中有多个promise,只有当所有的promise的状态都有成功时,才返回一个成功的promise对象。当需要执行多个异步任务,而各异步任务之间又没有依赖性时,可以用Promise.all方法,这样可以提高请求的效率,因为各个promise是并发执行的。
- Promise.any([数组])传入的参数是一个数组,数组中有多个promise,只要有一个promise的状态为成功时,就会返回一个成功的promise对象。
- Promise.race([数组])传入的参数是一个数组,数组中有多个promise,将最先改变状态的promise的状态作为该promise的状态
Promise的原理
手写一个简单的Promise 我们知道Promise里面有三种状态,分别是PENDING、FULFILLED、REJECTED,先在类中定义三个常量
static PENDING = '待定';
static FULFILLED = '成功';
static REJECTED = '拒绝';
当我们new一个Promise时,还要用constructor来初始化一些东西。
constructor(func) {
//初始化状态是待定的
this.status = '待定';
//promise当前所拿到的数据的值
this.result = null;
//resolve的回调队列
this.resolveCallbacks = [];
//reject的回调队列
this.rejectCallbacks = [];
try {
//改变this的指向,使resolve里面的this一直指向pormise对象
func(this.resolve.bind(this), this.reject.bind(this));
} catch (error) {
this.reject(error);
}
}
我们知道new Promise的时候,是需要传入一个函数的,这个函数又有两个参数,这两个参数都是函数,分别是resolve和reject,那么我们就来写一写resolve和reject方法吧
我们知道,resolve方法和reject方法都不是同步执行的,所以这里用了setTimeout()来将resolve和reject的内部执行模拟为异步。
resolve(result) {
setTimeout(() => {
if (this.status === Commitment.PENDING) {
this.status = Commitment.FULFILLED;
this.result = result;
this.resolveCallbacks.forEach(callback => {
callback(result);
})
}
})
}
reject(result) {
setTimeout(() => {
if (this.status === Commitment.PENDING) {
this.status = Commitment.REJECTED;
this.result = result;
this.rejectCallbacks.forEach(callback => {
callback(result);
})
}
})
}
最后再写then方法
then(onFULFILLED, onREJECTED) {
return new Commitment((resolve, reject) => {
onFULFILLED = typeof onFULFILLED === 'function' ? onFULFILLED : () => { };
onREJECTED = typeof onREJECTED === 'function' ? onFULFILLED : () => { };
if (this.status === Commitment.PENDING) {
this.resolveCallbacks.push(onFULFILLED);
this.rejectCallbacks.push(onREJECTED);
}
if (this.status === Commitment.FULFILLED) {
setTimeout(() => {
onFULFILLED(this.result);
})
}
if (this.status === Commitment.REJECTED) {
setTimeout(() => {
onREJECTED(this.result);
})
}
})
}
总的代码
class Commitment {
//常量全用大写字母来写
static PENDING = '待定';
static FULFILLED = '成功';
static REJECTED = '拒绝';
constructor(func) {
this.status = '待定';
this.result = null;
this.resolveCallbacks = [];
this.rejectCallbacks = [];
// try {
// func(this.resolve.bind(this), this.reject.bind(this));
// } catch (error) {
// this.reject(error);
// }
console.log(this)
func(this.resolve, this.reject);
}
resolve(result) {
console.log(this)
setTimeout(() => {
console.log(this)
if (this.status === Commitment.PENDING) {
this.status = Commitment.FULFILLED;
this.result = result;
this.resolveCallbacks.forEach(callback => {
callback(result);
})
}
})
}
reject(result) {
setTimeout(() => {
if (this.status === Commitment.PENDING) {
this.status = Commitment.REJECTED;
this.result = result;
this.rejectCallbacks.forEach(callback => {
callback(result);
})
}
})
}
then(onFULFILLED, onREJECTED) {
return new Commitment((resolve, reject) => {
onFULFILLED = typeof onFULFILLED === 'function' ? onFULFILLED : () => { };
onREJECTED = typeof onREJECTED === 'function' ? onFULFILLED : () => { };
if (this.status === Commitment.PENDING) {
this.resolveCallbacks.push(onFULFILLED);
this.rejectCallbacks.push(onREJECTED);
}
if (this.status === Commitment.FULFILLED) {
setTimeout(() => {
onFULFILLED(this.result);
})
}
if (this.status === Commitment.REJECTED) {
setTimeout(() => {
onREJECTED(this.result);
})
}
// resolve('这次一定')
})
}
}