jquery Deferred对象的好处(一)

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();//发起请求时显示等待页面,上面放个会转的菊花.gif

function 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
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值