Promise

所谓promise,简单来说是一个容器,里面保存着某个未来才会结束的事情(通常是一个异步操作)的结果,从语法上来讲Promise是一个对象,从它可以获取异步操作的消息。

Promise对象代表着一个异步操作,有三种状态,Pending(进行中),Fulfilled(已成功)和Rejected(已失败)。Promise对象的状态改变只能有两种可能:从Pending变为Fulfilled和从Pending变为Rejected。

基本用法

var promise = new Promise(function(resolve,regect){
    //异步代码
    if(异步操作成功){
        resolev(异步操作结果);
    }else{
        reject(错误对象)
    }
})
promise.then(function(value){},function(erroe){})

Promise构造函数接受一个函数作为参数,该函数的两个参数分别是resolve和reject,它们是两个函数,由Javascript引擎提供,不用自己部署。

resolve函数的作用是将Promise对象的状态从“未完成”变为“成功”,在异步操作成功时调用,并将异步操作的结果作为参数传递出去;

reject函数的作用是将Promise对象的状态从“未完成”变为“失败”。在异步操作失败时调用,并将异步操作报出的错误作为参数传递出去。

##Promise.prototype.then

Promise实例生成之后,可以用then方法来分别指定resolve状态和reject状态的回调。then方法可以接受两个回调函数作为参数,第一个回调函数是Promise对象的状态变为Resolved时调用的,第二个回调函数是Promise对象变为Rejected时调用的,其中,第二个函数是可选的。不一定要提供。这两个函数都接受Promise对象传出的值作为参数。

采用链式的then可以指定一组按照次序调用的回调函数,这样,前一个回调函数有可能返回地还是一个Promise对象,而后一个回调函数就会等待该Promise对象的状态发生改变后再被调用。

Promise.prototype.catch

Promise.prototype.catch方法是.then(null,reject)的别名,用于指定发生错误时的回调。

注意:Promise对象的错误具有冒泡的性质,会一直向后传递,直到被捕获为止,也就是说,错误总会被下一个catch语句捕获。一般来说,不要再then方法中定义Reject状态的回调函数,而应总是使用catch方法。

Promise.all

Promise.all方法用于将多个Promise实例包装成一个新的Promise实例。

var p = Promise.all([p1,p2,p3]);

p的状态由p1,p2,p3决定,分两种情况:

  1. 只有p1,p2,p3状态都变为Fulfiled,p的状态才会变为Fulfiled,此时,p1,p2,p3的返回值组成一个数组,传递给p的回调函数。
  2. 只要p1,p2,p3中有一个被Reject,p的状态就会变为Reject,此时,第一个被Reject的实例的返回值就会被传递给p的回调函数。

手动实现Promise.all

function promiseAll(promises) {
        return new Promise(function (resolve,reject) {
            //这个函数传入的参数首先必须要是一个数组,如果不是数组,则直接抛出异常
            if(!promises instanceof Array){
                throw new TypeError('Argument must be an Array');
            }
            //记录传入的promise对象的个数
            let len = promises.length;
            //记录状态为resolve的promise对象的个数
            let resolvedCount = 0;
            //保存一个promise对象的状态变为resolve之后的结果
            let resolvedArray = new Array(len);
            for(var i = 0;i<len;i++){
                (function (i) {
                    //使用Promise.resolve方法将传递进来的参数转换成promise对象的实例
                    Promise.resolve(promises[i]).then(value => {
                        //如果这个promise对象的状态变为resolve,就给负责技术的变量加1
                        resolvedCount++;
                        //将这个异步操作的结果保存在刚开始设定的数组里
                        resolvedArray[i] = value;
                        //当所有的promise对象的状态都变为resolve的时候,这个最外面返回的promise对象的状态变为resolve,然后将保存之前的所有promise实例的结果的数组返回
                        if(resolvedCount === len){
                            return resolve(resolvedArray);
                        }
                    },rej=>{
                        //如果有一个实例的状态变成了reject,则直接将要返回的这个promise实例对象的状态变为reject并返回即可。
                        return reject(rej);
                    }).catch(reason=>{
                        console.log(reason);
                    })
                })(i)
            }
        })
    }

Promise.race

Promise.race方法用于将多个Promise实例包装成一个新的Promise实例。和Promise.all不同的是,只要多个Promise实例中的一个改变了状态,包装出来的这个新实例的状态就会跟着改变。那个率先改变的Promise实例的返回值就会传递给p的回调函数。本身并不会关注这个改变状态的promise的实例的状态是变成了resolved还是rejected。

手动实现Promise.race

//有了promise.all的实现思路,再实现race方法就简单很多了
 function promiseRace(promises) {
        return new Promise(function (resolve,reject) {
            if(!promises instanceof array){
                throw new TypeError('Argument must be an Array');
            }
            let length = promises.length;
            for(var i = 0;i<length;i++){
                (function (i) {
                    Promise.resolve(promises[i]).then(res=>{
                        return resolve(res)
                    },rej=>{
                        return reject(rej)
                    }).catch(reason => {
                        console.log(reason);
                    })
                })(i)
            }
        })
    }

Promise.resolve

Promise.resolve方法将现有的对象转为Promise对象。

Promise.resolve('foo')等价于:
new Promise(function(resolve){
    resolve('foo');
})

  转载请注明: TomoFur Promise

 上一篇
文档对象模型(DOM) 文档对象模型(DOM)
文档对象模型(DOM)针对HTML和XML文档的一个API,DOM描绘了一个层次化的节点树,允许开发人员添加,移除和修改页面的一部分。 分级DOM1级定义了HTML和XML文档的底层结构,为基本的文档结构和查询提供了接口。 DOM2级对DO
2019-07-09
下一篇 
移动端1px适配 移动端1px适配
明明设置了边框是1px,你为什么在移动端上看起来像2px? 方法1:采用box-shadow .box{ box-shadow:0px 1px 1px -1px #000;//下边线 box-shadow:0px -1p
2019-07-02
  目录