json

2015-10-29 20:58

Promise接口实现之jQuery 的deferred对象

本文作者:IMWeb json 原文出处:IMWeb社区 未经同意,禁止转载

Promise是什么?

我们知道JavaScript是单线程,如果遇到某些耗时很长的javascript操作,那么其他的操作就必须等待。,通常的解决方法是将那些排在后面的操作,写成“回调函数”(callback)的形式。事先规定当他们结束运行后,应该调用那些函数。但是这样有一些显著缺点:

  • 回调函数往往写成函数参数的形式,导致函数的输入和输出非常混乱,整个程序的可阅读性差;
  • 回调函数往往只能指定一个,如果有多个操作,就需要改写回调函数。
  • 整个程序的运行流程被打乱,除错和调试的难度都相应增加。 Promises就是为了解决这些问题而提出的,它的主要目的就是取代回调函数,成为非同步操作的解决方案。它的核心思想就是让非同步操作返回一个对象,其他操作都针对这个对象来完成。

Jquery中的promise的实现——deferred对象

deferred对象是jQuery的回调函数解决方案,它解决了如何处理耗时操作的问题,对那些操作提供了更好的控制,以及统一的编程接口。 下面来看下他的具体的使用方法:

ajax操作的写法:

先看下传统写法:

    $.ajax({
    url: "test.html",
    success: function(){
      console.log(“成功”);
    },
    error:function(){
      console.log(“失败”);
    }
  });

其中success 和 error方法分别指定操作成功和失败的回调函数。
现在新的ajax操作的写法是这样的:

    $.ajax("test.html")
  .done(function(){console.log(“成功”); })
  .fail(function(){console.log(“失败”); });

done()相当于success方法,fail()相当于error方法。

注意,如果使用的是低于1.5.0版本的jQuery,返回的是XHR对象,没法进行链式操作;如果高于1.5.0版本,返回的是deferred对象,可以进行链式操作。

新的ajax操作也可以这样写:

    $.ajax("test.html").then(function(){
        console.log(“成功”);
        }, function(){
        console.log(“失败”); }
    );

这里介绍下deferred.then() 方法,有时为了省事,可以把done()和fail()合在一起写,这就是then()方法。如果then()有两个参数,那么第一个参数是done()方法的回调函数,第二个参数是fail()方法的回调方法。如果then()只有一个参数,那么等同于done()。

deferred对象的方法

$.deferred()方法

$.deferred()方法,作用是生成一个deferred对象,它允许你自由添加多个回调函数。

    var def = $.Deferred();
    def.done(function(){
        console.log(“成功”);
    }).fail(function(){
         console.log(“失败”);
    }).done(function(){
         console.log(“再一次成功”);
    })

回调函数可以添加任意多个,它们按照添加顺序执行。 其中,done() 和 fail()这两个方法都用来绑定回调函数。done()指定操作成功后的回调函数,fail()指定失败后的回调函数。

state方法

state方法用来返回deferred对象目前的状态,deferred对象有三种状态:操作还没有完成、操作成功、操作失败,对应state方法的返回值为:pending、resolved、rejected

    var deferred = $.Deferred();
    alert(deferred.state());  // "pending"
    deferred.resolve();
    alert(deferred.state());  // "resolved"

resolve() 和 reject()

前面说过deferred对象有三种执行状态----未完成,已完成和已失败。如果执行状态是"已完成"(resolved),deferred对象立刻调用done()方法指定的回调函数;如果执行状态是"已失败",调用fail()方法指定的回调函数;如果执行状态是"未完成",则继续等待,或者调用progress()方法指定的回调函数

    var def = $.Deferred();
        def.done(function(value) {
           alert(value);
    }).fail(function(){
        alert("hello");
    })
    def.resolve("hello world");

$.when()方法

$.when()接受多个deferred对象作为参数,当它们全部运行成功后,才调用resolved状态的回调函数,但只要其中有一个失败,就调用rejected状态的回调函数。它允许你为多个事件指定一个回调函数

    $.when($.ajax("test1.html"), $.ajax("test2.html"))
  .done(function(){ alert("成功"); })
  .fail(function(){ alert("失败"); });

上面的代码先执行两个操作$.ajax("test1.html")和$.ajax("test2.html"),如果都成功了,就运行done()指定的回调函数;如果有一个失败或都失败了,就执行fail()指定的回调函数。

注意如果when()它的参数返回的不是一个Deferred或Promise对象,那么when方法的回调函数将立即运行。

普通函数如何使用回调函数呢? 例如有这样的函数

     var wait = function(){
          setTimeout(function(){
              alert("执行完毕!");
          },3000);
     };
        wait();

现在为他指定回调函数

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

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

这样wait函数的返回值就是Deferred对象,when()函数能生效,wait()函数运行完,就会自动运行done()方法指定的回调函数。

always()

这个方法也是用来指定回调函数的,它的作用是,不管调用的是deferred.resolve()还是deferred.reject(),最后总是执行。

    $.ajax( "test.html" )
  .always( function() { alert("已执行!");} );
0条评论

    您需要 注册 一个IMWeb账号或者 才能进行评论。