ES6 Promise对象详解

promise对象是ES6提供的一个队列对象,可用于处理回调地狱问题。git

1 Promise的用法

首先先看一个ES5中常见的回调地狱。github

$.ajax({
    url:xx,
    success:function() {
        $.ajax({    //完成第一个请求的时候发起第二个请求
            url:xx.
            success:function() {
                $.ajax({    //完成第二个请求的时候发起第三个请求
                    url:xx.
                    success:function() {
                        $.ajax({
                            //继续发起下一次请求
                        });
                    }
                });
            }
        });
    }
});
复制代码

有一系列请求,他们须要前一个请求发送完毕时才能够发起请求,当嵌套多层请求时,代码的可读性和可维护性大大减低。经过Promise能够有效的解决这个问题。ajax

1.1 概念

promise是一个先进先出的队列,向这个队列中依次添加多个任务(每一个ajax请求能够视为一个任务),执行完毕的任务会被推出队列,而后执行下一个任务。数组

promise存在三个状态,分别是pending(任务等待或进行中)、fulfilled(任务成功完成,准备执行下一个任务)、rejected(任务完成但失败了,不执行下一个任务)。状态只能由pedding转为fulfilled/rejected,且不可逆。promise

Promise对象接收一个函数做为一个任务推动队列中,函数有resolve和reject两个参数,调用resolve()表示将状态由pedding转为fulfilled,调用reject()表示将状态由pedding转为rejected。下面看一个列子。bash

new Promise(function(resolve,reject) {
    setTimeout(function() {
        var ran=Math.random();
        if(ran<0.5) {
            resolve(ran);
        }
        else {
            reject(ran);
        }
    },1000);
})
.then(function(ran) {
	console.log(ran+'大于0.5');
},function(ran) {
	console.log(ran+'小于0.5');
});
复制代码

在上面的例子中,先定义了一个Promise对象,设置了一个定时器,在1秒以后随机一个0-1的数,数值小于0.5时,调用resolve()方法将状态由pedding转为fulfilled,数值大于0.5则调用reject()方法,将状态由pedding转为rejected。dom

一旦状态由pedding转为fulfilled或rejected时,Promise对象将当前任务推出队列,同时执行下一个任务,下一个任务经过Promise对象的then方法传入,then方法接收两个函数,上一个任务的状态为fulfilled时执行第一个函数,上一个任务的状态为rejected时执行第二个函数。第二个参数能够不传入。模块化

1.2 promise改写回调地狱

经过then方法能够将回调地狱改写为:函数

new Promise(function(resolve,reject){
    $.ajax({        //第一个请求
        url:xx,
        success:function({
            resolve();
        });
    })
})
.then({             //完成第一个请求的时候发起第二个请求
    $.ajax({
        url:xx,
        success:function({
            resolve();
        });
    })
})
.then({             //完成第二个请求的时候发起第三个请求
    $.ajax({
        url:xx,
        success:function({
            resolve();
        });
    })
})
复制代码

2 Promise提供的方法

除了then(),Promise还提供了一些经常使用的静态方法。post

2.1 all()

有时候,咱们但愿在执行某个任务以前,必需要先执行其余的几个任务,不使用promise的时候,咱们会使用一个参数做为进度条,下面是例子

//不使用Promise
var prog=0;     //定义进度条,prog满100时,执行第三个任务
$.ajax({            //第一个任务
    url:xx
    success:function() {
        prog+=50;   //进度条增长50
        next();     //查看prog是否满100,满了则执行第三个任务
    }
});
$.ajax({            //第二个任务
    url:xx
    success:function() {
        prog+=50;   //进度条增长50
        next();     //查看prog是否满100,满了则执行第三个任务
    }
});
function next() {
    if(prog==100) {
        $.ajax({    //第一个任务与第二个任务同时完成后,才执行第三个任务
            
        });
    }
}
复制代码

Promise提供了一个静态方法all,该方法接收一个Promise数组,数组内的全部任务同时执行,只有全部任务执行完毕时,才将状态由pedding转为fulfilled。

//使用Promise
let promiseArr=[];
let promise1=new Promise(function(resolve,reject) {
    $.ajax({            //第一个任务
        url:xx
        success:function() {
        }
    });
});
promiseArr.push(promise1);
let promise2=new Promise(function(resolve,reject) {
    $.ajax({            //第二个任务
        url:xx
        success:function() {
        }
    });
});
promiseArr.push(promise2);
Promise.all(promiseArr)
.then(function() {
    $.ajax({    //第一个任务与第二个任务同时完成后,才执行第三个任务
            
    });
});
复制代码

2.2race()

race也是Promise的静态方法,用法与all()相似,也是接收一个Promise数组,不一样点是all()方法是等数组中的全部任务同时执行,且全部任务执行完毕才将状态由pedding转为fulfilled,race()方法是数组中的全部任务同时执行,有一个任务执行完毕时,就将状态由pedding转为fulfilled。

2.3resolve()

recolve()方法接收一个变量,根据变量的类型有不一样的表现

  • 接收一个Promise对象,直接将该Promise对象返回。
  • 接收一个带有then方法的对象,将对象转换为Promise对象后执行then方法。
  • 接收的变量不是Promise对象也没有then方法,返回resolve状态的Promsie对象。

2.4reject()

reject()方法直接返回一个reject状态的Promise对象。

更多ES6精髓如模块化请看ES6快速入门

3交流

若是这篇文章帮到你了,以为不错的话来点个Star吧。 github.com/lizijie123