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 条评论
登录 后参与评论

相关文章

来自专栏Leetcode名企之路

jvm类加载机制

类从被加载到虚拟机内存中开始,到卸载出内存为止,它的整个生命周期包括:加载、验证、准备、解析、初始化、使用和卸载七个阶段。

14030
来自专栏IMWeb前端团队

Nodejs进阶:服务端字符编解码&乱码处理

本文作者:IMWeb 陈映平 原文出处:IMWeb社区 未经同意,禁止转载 写在前面 在web服务端开发中,字符的编解码几乎每天都要打交道。编解码一旦...

437100
来自专栏大内老A

如何在EHAB(EntLib)中定义”细粒度”异常策略?

为了解决EntLib的EHAB(Exception Handling Application Block)只能在异常类型级别控制异常处理策略的局限,我在很久之前...

19290
来自专栏PHP在线

开发常用知识点

php允许传递任意个参数: function getArg($a="",$b=""){ echo "one:".$a."<br/>"; echo "two"...

420140
来自专栏salesforce零基础学习

salesforce 零基础学习(二十四)解析csv格式内容

salesforce中支持对csv格式的内容批量导入,可以使用dataloader,然而有些情况下,当用户没有相关权限使用dataloader导入情况下,就的需...

267100
来自专栏用户2442861的专栏

java类加载过程

转载请注明出处:http://blog.csdn.net/ns_code/article/details/17881581

26210
来自专栏用户2442861的专栏

【深入Java虚拟机】之四:类加载机制

转载请注明出处:http://blog.csdn.net/ns_code/article/details/17881581

7210
来自专栏CodingToDie

java 代理

java 代理 代理(Proxy)是一种设计模式,提供了对目标对象另外的访问方式;即通过代理对象访问目标对象.这样做的好处是:可以在目标对象实现的基础上,增强额...

37040
来自专栏用户2442861的专栏

《Java虚拟机原理图解》 1.1、class文件基本组织结构

http://blog.csdn.net/luanlouis/article/details/39892027

12120
来自专栏python3

python类(class)

类(Class): 用来描述具有相同的属性和方法的对象的集合。它定义了该集合中每个对象所共有的属性和方法。对象是类的实例,把所有相似的功能都封装到一个类里,最理...

12030

扫码关注云+社区

领取腾讯云代金券