javascript异步处理与Jquery的deferred对象总结

这是项目组老大整理的一些关于jquery 异步处理请求,以及使用 jquery deferred 对象的一些常见方法。虽然是项目上总结出来的。但也比较通用,分享在这里。

•所有的Ajax操作都采用异步处理。
•采用Jquery的Deffered对象来处理异步调用。
•因为是异步调用,所以$.Ajax函数的返回值不代表返回的结果,只是一个Deffered对象。
•Ajax调用完成后执行的逻辑可以写成函数作为参数传递给Deffered对象的done(), fail(), always()函数来执行。
•如果一个函数包含Ajax调用,那么这个函数必须将Ajax返回的异步对象作为自己的返回值,否则函数的调用者无法保证后续代码的正常执行顺序。

例如:
程序代码 程序代码


function readData(){
    $.ajax({ url:"test", dataType:"json" })
    .done(function() {
        //....
    });
}

readData();
//...这里想添加一些后续处理,但程序将在Ajax回调前执行,所以无法达到预期目的
正确的代码:

function readData(){
    return $.ajax({ url:"test", dataType:"json" })
    .done(function() {
        //....
    });
}

readData().done(function () {
    //...想添加的后续处理可以加在这里处理
});


•如果需要调用多个Ajax请求,请注意Ajax请求是否可以同时进行,如果可以应该使用when()函数来同时执行,以提高程序的运行效率和可读性。

•deferred对象有一个方法promise(),可以阻止其他代码修改deferred对象的状态,也就是其他代码调用reslove()和reject()无效。

程序代码 程序代码

  var dtd = $.Deferred(); // 新建一个Deferred对象
  var wait = function(dtd){
      var tasks = function(){
          alert("执行完毕!");
          dtd.resolve(); // 改变Deferred对象的执行状态
      };
      setTimeout(tasks,5000);
      return dtd;
  };

  wait(dtd)
  .done(function(){ alert("成功了!"); })
  .fail(function(){ alert("出错啦!"); });

  dtd.resolve();   //这里修改了dtd对象的状态,导致立刻出现“成功了!”的提示
  
正确的例子:

  var dtd = $.Deferred(); // 新建一个Deferred对象
  var wait = function(dtd){
      var tasks = function(){
          alert("执行完毕!");
          dtd.resolve(); // 改变Deferred对象的执行状态
      };
      setTimeout(tasks,5000);
      return dtd.promise(); // 返回promise对象
  };

  wait(dtd)
  .done(function(){ alert("成功了!"); })
  .fail(function(){ alert("出错啦!"); });

  dtd.resolve();   //这里修改dtd对象的状态无效


•一些情况的处理:

1.嵌套异步操作的处理。

如果一个函数内部执行异步任务,并且在异步任务的done回调内会嵌套另一个异步任务,那么简单返回第一个异步任务的返回值是不行的,需要另外自行定义一个Deferred对象作为返回值。
程序代码 程序代码

function loadComponent(id){
    var dtd = $.Deferred();
    //loadScript将异步加载一个js文件,所以返回值是一个Deffered对象
    return loadScript(id)
    .done(function() {
        //js加载后,触发component的load事件,此事件内将使用Ajax获取页面模板和数据,生成最终的html
        app.getComponent(id).trigger("load")
       .done( function(){
            dtd.reslove(agruments);
        }).fail( function(){
            dtd.reject(agruments);
        });
    });
    //返回自定义的dtd对象,才能保证返回值的done回调在load事件完成后执行
    return dtd;
}


2.一个函数内同时包含同步和异步case的处理。

/* 这个函数返回一个异步对象,当异步对象执行done时,表示component被加载完成 */
程序代码 程序代码

function requireComponent(id){
    if (this.components[id]){
        //如果component已经被加载,直接返回一个reslove的异步对象,否则返回值内容与else分支不同,后续代码难以处理
        var dtd = $.Deferred();
        dtd.reslove(this.getComponent(id));
        return dtd;
    }
    else{
        //如果component未被加载,loadScript将异步加载JavaScript并执行,然后将被加载的component放入this.components
        return loadScript(id);
    }
}

•Jquery异步模型有一个缺点,就是缺乏类似wait操作的处理能力,如果多个异步调用要顺序发生时,就要在done里面嵌套处理,影响代码可读性.

程序代码 程序代码

aSyncTask1.done( function () {
    //...第一个操作完成后的处理
    asyncTask2.done( function () {
        //...第二个操作完成后的处理
        asyncTask3.done( function () {
            //...第三个操作完成后的处理
        });
    })
})



除非申明,文章均为一号门原创,转载请注明本文地址,谢谢!
文章来自: 本站原创
引用通告: 查看所有引用 | 我要引用此文章
Tags: javascript jquery deferred
相关日志:
评论: 0 | 引用: 0 | 查看次数: -
发表评论
昵 称:
密 码: 游客发言不需要密码.
内 容:
验证码: 验证码
选 项:
虽然发表评论不用注册,但是为了保护您的发言权,建议您注册帐号.