jquery Deferred对象的好处(一)

来源:互联网 发布:keras与tensorflow 编辑:程序博客网 时间:2024/05/18 02:46

jquery Deferred对象的好处 (一)

1、引子

先看一个普通的业务逻辑请求

$.ajax({    url:'test.htm',    data:{        userId:'001',        param1:"a1",        param2:'a2'        ...    },    succsss:function(){        ...    }});

这是一段普通的请求代码,里面携带了userId以及其他的一些业务参数。userId是用来识别用户身份的,几乎每个业务请求都要带上它。
现在为考虑到安全性将userId存在于服务器的session中(用户登录时生成),下次请求是浏览器只需cookies中的信息带过去就行了,而无需带上userId。
传统的网站session过期时往往要用户去重新登录,而现在产品经理改了需求,业务请求身份过期时不跳登录,而是激活身份,正常完成业务请求。
好!easy啦。。无非是再多发一个激活身份的请求(先叫他refreshUrl),上代码

//以ajax请求同步的方式实现var tokenResult=true;//代表身份是否过期的变量  function tokenRefresh(){    var result=false;    $.ajax({        url:refreshUrl,        ansy:false,        data:{            param1:"a1",            param2:'a2'            ...        },        succsss:function(){            if(sussess){                //刷新session                result=true;                return;            }            else {                //error catch            }            //doSomethings..        }    });    return result;}function doSomethings(){    $.ajax({        url:'test.htm',        ansy:false,        data:{            param1:"a1",            param2:'a2'            ...        },        succsss:function(){            if(errorCode===-1){                //身份过期                tokenResult=false;                return;            }            //doSomethings..        }    });}doSomethings();if(!tokenResult&&tokenRefresh()){    //session过期时刷新session,再发一次请求    doSomethings();}

代码量是大了点但是勉强是可以使用的而且安全性也可以保证。过几天产品经理又来改需求了(又改需求。。),他说有时候发用户反馈业务请求时会出现几秒钟的空白时间,需要价格等待界面。说加就加,代码就这样写

//其他的不变无非就加个等待页面的显示和隐藏showWaitUI();//发起请求时显示等待页面,上面放个会转的菊花.giffunction doSomethings(){    $.ajax({        url:'test.htm',        ansy:false,        data:{            param1:"a1",            param2:'a2'            ...        },        succsss:function(){            if(errorCode===-1){                //身份过期                tokenResult=false;                return;            }            else if(success){                //doSomethings...                hideWaitUI();//隐藏等待框                //执行正常的业务逻辑            }        }    });}doSomethings();if(!tokenResult&&tokenRefresh()){    //session过期时刷新session,再发一次请求    doSomethings();}

现在问题来了,当你运行调试时发现等待页面是出来了但是小菊花转不动了,一查发现是ajax同步请求阻塞了UI线程,那还有什么办法只好使用异步呗。

//修改代码function tokenRefresh(doSthFun){    $.ajax({        url:refreshUrl,        ansy:false,        data:{            param1:"a1",            param2:'a2'            ...        },        succsss:function(){            if(sussess){                //刷新session,继续执行业务操作                doSthFun()            }            else {                //error catch            }            //doSomethings..        }    });}function doSomethings(){    $.ajax({        url:'test.htm',        ansy:false,        data:{            param1:"a1",            param2:'a2'            ...        },        succsss:function(){            if(errorCode===-1){                //身份过期                tokenRefresh(doSomethings);                return;            }            else if(success){                //doSomethings...                hideWaitUI();//隐藏等待界面                //执行正常的业务逻辑            }        }    });}showWaitUI();//显示等待界面doSomethings();//执行业务操作

但是段代码嵌套调用逻辑性和可读性都很差,而且不安全,很容易发生死锁,从而陷入回调地狱,因此这里引出Deferred对象解决上述问题。

2、Deferred 对象的介绍

简单说,deferred对象就是jQuery的回调函数解决方案。在英语中,defer的意思是”延迟”,所以deferred对象的含义就是”延迟”到未来某个点再执行。
它解决了如何处理耗时操作的问题,对那些操作提供了更好的控制,以及统一的编程接口。
在高于1.5版本的jquery库中ajax请求返回的都是一个deferred对象,因此ajax请求的回调可以写成链式的形式

$.ajax({    url:'text.html'}).done(function(data){    //doSthings With success...}).fail(function(error){    //doSthings With fail...});

done()相当于success方法,fail()相当于error方法。采用链式写法以后,代码的可读性大大提高。
deferred对象的最大优点,就是它把这一套回调函数接口,从ajax操作扩展到了所有操作。也就是说,任何一个操作不管是ajax操作还是本地操作,也不管是异步操作还是同步操作都可以使用deferred对象的各种方法,指定回调函数。

//for example...//定义一个很耗时的操作函数var doSomethings=function(){    var tasks = function(){        if(succsee){            alert('success');        }else{            alert('fail');        }    }    setTimeOut(tasks,50000);}

如果我们将它作为指定函数,可以用$.when()实现。由于$.when()只支持deferred对象。因此需要改写上述代码为。

var doSomethings=function(){     // 新建一个deferred对象 var deferred= $.Deferred();    var tasks = function(){        if(succsee){            alert('success');            //设置执行状态为已完成,执行done回调            deferred.resolve(data);        }else{        //设置执行状态为失败,执行fail回调            deferred.reject(data);            alert('fail');        }    }    setTimeOut(tasks,50000);    //调用deferred对象的promise方法,让执行状态不能再外部被改变    return deferred.promise();}$when(doSomethings()).done(function(data){    //dosomething with success...}).fail(function(){    //dosomething with fail...})

3、使用

根据deferred的知识,原来的业务操作请求代码可以改写成如下形式:

var deferred=$.Deferred(); // 新建一个Deferred对象function doSomethings(){    $.ajax({        url:'test.htm',        ansy:false,        data:{            param1:"a1",            param2:'a2'            ...        },        succsss:function(data){            if(errorCode===-1){                //身份过期                deffered.resolve(false);                return;            }            else if(success){                //doSomethings...                hideWaitUI();//隐藏等待界面                //执行正常的业务逻辑            }            deffered.resolve(true);        },        error:function(){            deferred.reject();        }    });    return deferred.promise();}showWatiUI();//显示等待界面$.when(doSomethings()).done(fuction(tokenResult){    if(!tokenResult){        tokenRefresh();        doSomethings();    }}).always(function(){    //无论成功失败读执行    hideWaitUI();});

那么问题也解决了,再次运行程序,会发现菊花已经可以转动了。
注:(如果想对deferred对象有更多的了解,请阅读阮一峰老师的《jQuery的deferred对象详解》)
http://www.ruanyifeng.com/blog/2011/08/a_detailed_explanation_of_jquery_deferred_object.html

0 0
原创粉丝点击