美文网首页
ES6之Promise对象

ES6之Promise对象

作者: 四月天__ | 来源:发表于2017-09-19 10:39 被阅读20次

    本文大部分内容是阮一峰老师的文章,这里搬过来也是为了自己记录,想看更加详细的教程请移步阮一峰老师个人博客

    1.Promise.prototype.then()

    then方法返回的是一个新的Promise实例(注意,不是原来那个Promise实例)。因此可以采用链式写法,即then()方法后面再调用另一个 then()方法。

    getJSON("/posts.json").then(function(json) {
      return json.post;
    }).then(function(post) {
      // ...
    });
    

    采用链式的 then ,可以指定一组按照次序调用的回调函数。这时,前一个回调函数,有可能返回的还是一个Promise对象(即有异步操作),这时后一个回调函数,就会等待该Promise对象的状态发生变化,才会被调用。

    getJSON("/post/1.json").then(function(post) {
      return getJSON(post.commentURL);
    }).then(function funcA(comments) {
      console.log("resolved: ", comments);
    }, function funcB(err){
      console.log("rejected: ", err);
    });
    

    上面代码中,第一个then方法指定的回调函数,返回的是另一个Promise对象。这时,第二个then()方法指定的回调函数,就会等待这个新的Promise对象状态发生变化。如果变为resolved,就调用funcA,如果状态变为rejected,就调用funcB

    上面代码对应的更简洁的箭头函数写法为:

    getJSON("/post/1.json").then(
      post => getJSON(post.commentURL)
    ).then(
      comments => console.log("resolved: ", comments),
      err => console.log("rejected: ", err)
    );
    

    看下面一个使用的综合案例

       let pro = new Promise(function(resolve,reject){
    
            if(true){
                //调用操作成功方法
                resolve('操作成功');
            }else{
                //调用操作异常方法
                reject('操作异常');
            }
        });
    
        //用then处理操作成功,catch处理操作异常
        pro.then(requestA)
            .then(requestB)
            .then(requestC)
            .catch(requestError);
    
        function requestA(){
            console.log('请求A成功');
            return '请求B,下一个就是你了';
        }
        function requestB(res){
            console.log('上一步的结果:'+res);
            console.log('请求B成功');
            return '请求C,下一个就是你了';
        }
        function requestC(res){
            console.log('上一步的结果:'+res);
            console.log('请求C成功');
        }
        function requestError(){
            console.log('请求失败');
        }
    
        //打印结果:
        //请求A成功
        //上一步的结果:请求B,下一个就是你了
        //请求B成功
        //上一步的结果:请求C,下一个就是你了
        //请求C成功
    

    案例中,先是创建一个实例,还声明了4个函数,其中三个是分别代表着请求A,请求B,请求C;有了then方法,三个请求操作再也不用层层嵌套了。我们使用then方法,按照调用顺序,很直观地完成了三个操作的绑定,并且,如果请求B依赖于请求A的结果,那么,可以在请求A的程序用使用return语句把需要的数据作为参数,传递给下一个请求,案例中我们就是使用return实现传递参数给下一步操作的。

    Promise.all( )方法

    Promise.all( )方法:接受一个数组作为参数,数组的元素是Promise实例对象,当参数中的实例对象的状态都为fulfilled时,Promise.all( )才会有返回。

    //创建实例pro1
        let pro1 = new Promise(function(resolve){
            setTimeout(function () {
                resolve('实例1操作成功');
            },5000);
        });
        
        //创建实例pro2
        let pro2 = new Promise(function(resolve){
            setTimeout(function () {
                resolve('实例2操作成功');
            },1000);
        });
    
        
        Promise.all([pro1,pro2]).then(function(result){
            console.log(result);
        });
        //打印结果:["实例1操作成功", "实例2操作成功"]
    

    上述案例,我们创建了两个Promise实例:pro1和pro2,我们注意两个setTimeout的第二个参数,分别是5000毫秒和1000毫秒,当我们调用Promise.all( )方法的时候,会延迟到5秒才控制台会输出结果。

    因为1000毫秒以后,实例pro2进入了成功fulfilled状态;此时,Promise.all( )还不会有所行动,因为实例pro1还没有进入成功fulfilled状态;等到了5000毫秒以后,实例pro1也进入了成功fulfilled状态,Promise.all( )才会进入then方法,然后在控制台输出:["实例1操作成功","实例2操作成功"]。

    这个方法有什么用呢?一般这样的场景:我们执行某个操作,这个操作需要得到需要多个接口请求回来的数据来支持,但是这些接口请求之前互不依赖,不需要层层嵌套。这种情况下就适合使用Promise.all( )方法,因为它会得到所有接口都请求成功了,才会进行操作。

    Promise.race( )方法

    另一个类似的方法是Promise.race()方法:它的参数要求跟Promise.all( )方法一样,不同的是,它参数中的promise实例,只要有一个状态发生变化(不管是成功fulfilled还是异常rejected),它就会有返回,其他实例中再发生变化,它也不管了。

        //初始化实例pro1
        let pro1 = new Promise(function(resolve){
            setTimeout(function () {
                resolve('实例1操作成功');
            },4000);
        });
    
        //初始化实例pro2
        let pro2 = new Promise(function(resolve,reject){
            setTimeout(function () {
                reject('实例2操作失败');
            },2000);
        });
    
        Promise.race([pro2,pro1]).then(function(result){
            console.log(result);
        }).catch(function(error){
            console.log(error);
        });
        //打印结果:实例2操作失败
    

    同样是两个实例,实例pro1不变,不同的是实例pro2,这次我们调用的是失败函数reject。

    由于pro2实例中2000毫秒之后就执行reject方法,早于实例pro1的4000毫秒,所以最后输出的是:实例2操作失败。

    以上就是对Promise对象的内容讲解,上面提到了一个概念:回调地狱;指的是过多地使用回调函数嵌套,使得调试和维护起来极其的不便。

    参考:微信文章教你如何使用ES6的Promise对象
    https://segmentfault.com/a/1190000002928371
    http://www.cnblogs.com/tugenhua0707/p/7337022.html

    相关文章

      网友评论

          本文标题:ES6之Promise对象

          本文链接:https://www.haomeiwen.com/subject/ftkwsxtx.html