zoukankan      html  css  js  c++  java
  • Promise

    Promise

    Promise已经获得所有现代浏览器的支持,是时候使用它来重构你的代码了。

    Promise可以改变我们代码的书写方式,让代码的逻辑和结构更加清晰,帮助你从回调地狱中解脱。

    回调模式

    下面是一个简单的例子,如果你还不知道它是用来干什么的话。

    function get(url,callback){
                var xhr = new XMLHttpRequest();
                xhr.open('GET',url,true);
                xhr.onload=function(){
                    if(xhr.status===200){
                        callback(null,xhr.response);
                    }else{
                        callback(Error(xhr.statusText));
                    }
                };
                xhr.onerror=function(){
                    callback(Error("Network Error!"));
                };
                xhr.send();
        }
    function log(err,data){
        if(err) return console.log(err);
        console.log(data)
    }
    
    get("someurl...",log);
    

    上面的函数通过ajax请求获取指定url返回的数据,并且在控制台打印出来。因为要在ajax请求成功,并且返回数据之后,我们才能执行log函数,所以,按照习惯,我们使用了回调函数。

    现在,如果有一个新的需求,我们在log函数执行之后,还要执行另一个操作,比如说将ajax请求返回的结果进行一系列的处理。

    function handleData(data){
        ......
    }
    

    按照常规的想法,我们需要把这个函数当作回调传入到log函数中,这样,当打印完毕后,再执行handleData。那么,log函数需要做一些修改:

    function log(err,data,callback){
        if(err) return console.log(err);
        console.log(data);
        callback && callback(data);
    }
    

    由于log函数是作为回调传入get函数中的,log函数自身也有一个函数参数作为回调,我们需要在get函数中传入它。

        function get(url, callback, logcallback) {
            var xhr = new XMLHttpRequest();
            xhr.open('GET', url, true);
            xhr.onload = function() {
                if (xhr.status === 200) {
                    callback(null, xhr.response, logcallback);
                } else {
                    callback(Error(xhr.statusText), null, logcallback);
                }
            };
            xhr.onerror = function() {
                callback(Error("Network Error!"));
            };
            xhr.send();
        }
    

    现在我们的流程设计完毕,开始调用:

    get("someurl",log,handleData);
    

    如果我们的数据需要经过一系列的处理,那么这个回调参数的个数会越来越多。

    使用Promise

    同样的需求使用Promise来解决,代码如下:

    get("someurl").then(log).then(handleData);
    

    代码是不是变简洁而又清晰?不过,在实现这样的代码之前,我们要对以上的函数做出一些修改,让他们华丽的变身。

    首先,我们要修改get函数:

    function get(url){
            var promise = new Promise(function(resolve,reject){
                var xhr = new XMLHttpRequest();
                xhr.open('GET',url,true);
                xhr.onload=function(){
                    if(xhr.status===200){
                        resolve(xhr.response);
                    }else{
                        reject(Error(xhr.statusText));
                    }
                };
                xhr.onerror=function(){
                    reject(Error("Network Error!"));
                };
                xhr.send();
            });
            return promise;
        }
    

    可以看到,get函数现在返回了一个promise对象。而promise对象具有then方法,所以我们可以get函数返回promise之后,直接调用它的then方法,then方法也返回一个promise对象,所以可以继续调用then方法,如果这方面你还不是很懂的话,想想jquery的链式调用吧!

    promise对象的生成

    在这里我们使用的是最基本的方法,通过构造函数:

    var promise = new Promise(function(resolve,reject){
        ......
    });
    

    省略掉的部分就是你原本的代码逻辑,唯一不同的一点,就是对于返回值的处理。

    对于ajax请求来说,有两种状态:请求成功,请求失败。 当请求成功时,我们把数据返回,不过这里用resolve 代替return。

    resolve(xhr.response);
    

    当请求失败时,我们把错误返回,这里用reject代替return。

    reject(xhr.statusText);
    

    我们暂且不考虑其他情况。

    resolve 和 reject

    它们代替了我们平时所使用的return,这样做的目的是什么?

    我们知道,ajax请求是需要花费时间的。我们要等待请求并返回结果。 当结果返回时,不管是数据或者错误,这个请求都是确确实实的发生并且完成了。而resolve和reject就是把这个promise对象的状态进行改变,由等待状态改变至完成状态。

    如果都是把promise对象的状态改变为完成状态的话,为什么要用两个不同的名称呢,都用resolve不就行了嘛?

    我们知道,ajax请求完成了,但是完成也有两种状态。一种是成功获取到数据的完成,一种是请求出错的完成。但是这两种完成都是完成,都经历了发送请求,等待响应,返回结果的过程。

    当以resolve方式改变promise对象的状态至完成状态时,会调用后续的then方法中第一个参数,做为回调。 当以reject方式改变promise对象的状态至完成状态时,调用then方法中第二个参数作为回调,或者catch方法中的参数作为回调。

    get("someurl").then(log,logerr);    
    get("someurl").then(log).catch(logerr);
    
  • 相关阅读:
    软件破解系列之OD中断方法
    C#获取类名为Internet_Explorer_Server控件的内容
    C#重启网卡(支持xp和win7)
    软件开发专业技术名词的解释
    一些软件设计的原则
    AntlrWorks的Open没有反应,安装JDK6即可解决
    向大家推荐《思考中医》,这本书对我来说算是中医启蒙了 无为而为
    面对富裕对于贫穷的几乎是天生傲慢我们要呐喊: 我们并不笨,我们只是穷读新科诺贝尔文学奖得主,奥尔罕·帕慕克作品有感 无为而为
    推荐一本书《罗伯特议事规则(Robert's Rules of Order) 》,也许对于想要参与管理的技术人员来说是很有用的 无为而为
    再次发布一个工作地点在上海的Biztalk专家招聘 无为而为
  • 原文地址:https://www.cnblogs.com/zhangfengyang/p/5416372.html
Copyright © 2011-2022 走看看