来自 前端知识 2019-12-07 15:32 的文章
当前位置: 金沙澳门官网网址 > 前端知识 > 正文

jQuery的Deferred对象概述,jQuery之Deferred对象详整

jQuery的Deferred对象概述

2017/03/02 · CSS

本文由 伯乐在线 - HansDo 翻译,叙帝利 校稿。未经许可,禁止转载!
英文出处:Aurelio De Rosa。欢迎加入翻译组。

很久以来,JavaScript 开发者们习惯用回调函数的方式来执行一些任务。最常见的例子就是利用 addEventListener()函数来添加一个回调函数, 用来在指定的事件(如 clickkeypress)被触发时,执行一系列的操作。回调函数简单有效——在逻辑并不复杂的时候。遗憾的是,一旦页面的复杂度增加,而你因此需要执行很多并行或串行的异步操作时,这些回调函数会让你的代码难以维护。

ECMAScript 2015(又名 ECMAScript 6) 引入了一个原生的方法来解决这类问题:promises。如果你还不清楚 promise 是什么,可以阅读这篇文章《Javascript Promise概述》。jQuery 则提供了独具一格的另一种 promises,叫做 Deferred 对象。而且 Deferred 对象的引入时间要比 ECMAScript 引入 promise 早了好几年。在这篇文章里,我会介绍 Deferred 对象和它试图解决的问题是什么。

jQuery之Deferred对象详解,jquerydeferred

deferred对象是jQuery对Promises接口的实现。它是非同步操作的通用接口,可以被看作是一个等待完成的任务,开发者通过一些通过的接口对其进行设置。事实上,它扮演代理人(proxy)的角色,将那些非同步操作包装成具有某些统一特性的对象,典型例子就是Ajax操作、网页动画、web worker等等。

jQuery的所有Ajax操作函数,默认返回的就是一个deferred对象。

Promises是什么

由于JavaScript单线程的特点,如果某个操作耗时很长,其他操作就必需排队等待。为了避免整个程序失去响应,通常的解决方法是将那些排在后面的操作,写成“回调函数”(callback)的形式。这样做虽然可以解决问题,但是有一些显著缺点:

1.回调函数往往写成函数参数的形式,导致函数的输入和输出非常混乱,整个程序的可阅读性差;
2.回调函数往往只能指定一个,如果有多个操作,就需要改写回调函数。
3.整个程序的运行流程被打乱,除错和调试的难度都相应增加。

Promises就是为了解决这些问题而提出的,它的主要目的就是取代回调函数,成为非同步操作的解决方案。它的核心思想就是让非同步操作返回一个对象,其他操作都针对这个对象来完成。比如,假定ajax操作返回一个Promise对象。

复制代码 代码如下:

var promise = get('');

然后,Promise对象有一个then方法,可以用来指定回调函数。一旦非同步操作完成,就调用指定的回调函数。

复制代码 代码如下:

promise.then(function (content) {
  console.log(content)
})

可以将上面两段代码合并起来,这样程序的流程看得更清楚。

复制代码 代码如下:

get(' (content) {
  console.log(content)
})

在1.7版之前,jQuery的Ajax操作采用回调函数。

复制代码 代码如下:

$.ajax({
    url:"/echo/json/",
    success: function(response)
    {
       console.info(response.name);
    }
});

1.7版之后,Ajax操作直接返回Promise对象,这意味着可以用then方法指定回调函数。

复制代码 代码如下:

$.ajax({
    url: "/echo/json/",
}).then(function (response) {
    console.info(response.name);
});

deferred对象的方法

$.deferred()方法

作用是生成一个deferred对象。

复制代码 代码如下:

var deferred = $.deferred();

done() 和 fail()

这两个方法都用来绑定回调函数。done()指定非同步操作成功后的回调函数,fail()指定失败后的回调函数。

复制代码 代码如下:

var deferred = $.Deferred();
deferred.done(function(value) {
   alert(value);
});

它们返回的是原有的deferred对象,因此可以采用链式写法,在后面再链接别的方法(包括done和fail在内)。

resolve() 和 reject()

这两个方法用来改变deferred对象的状态。resolve()将状态改为非同步操作成功,reject()改为操作失败。

复制代码 代码如下:

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

一旦调用resolve(),就会依次执行done()和then()方法指定的回调函数;一旦调用reject(),就会依次执行fail()和then()方法指定的回调函数。

state方法

该方法用来返回deferred对象目前的状态。

复制代码 代码如下:

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

该方法的返回值有三个:

1.pending:表示操作还没有完成。
2.resolved:表示操作成功。
3.rejected:表示操作失败。

notify() 和 progress()

progress()用来指定一个回调函数,当调用notify()方法时,该回调函数将执行。它的用意是提供一个接口,使得在非同步操作执行过程中,可以执行某些操作,比如定期返回进度条的进度。

复制代码 代码如下:

 var userProgress = $.Deferred();
    var $profileFields = $("input");
    var totalFields = $profileFields.length
    userProgress.progress(function (filledFields) {
        var pctComplete = (filledFields/totalFields)*100;
        $("#progress").html(pctComplete.toFixed(0));
    });
    userProgress.done(function () {
        $("#thanks").html("Thanks for completing your profile!").show();
    });
    $("input").on("change", function () {
        var filledFields = $profileFields.filter("[value!='']").length;
        userProgress.notify(filledFields);
        if (filledFields == totalFields) {
            userProgress.resolve();
        }
    });

then()

then()的作用也是指定回调函数,它可以接受三个参数,也就是三个回调函数。第一个参数是resolve时调用的回调函数,第二个参数是reject时调用的回调函数,第三个参数是progress()方法调用的回调函数。

复制代码 代码如下:

deferred.then( doneFilter [, failFilter ] [, progressFilter ] )

在jQuery 1.8之前,then()只是.done().fail()写法的语法糖,两种写法是等价的。在jQuery 1.8之后,then()返回一个新的deferred对象,而done()返回的是原有的deferred对象。如果then()指定的回调函数有返回值,该返回值会作为参数,传入后面的回调函数。

复制代码 代码如下:

var defer = jQuery.Deferred();
defer.done(function(a,b){
            return a * b;
}).done(function( result ) {
            console.log("result = " + result);
}).then(function( a, b ) {
            return a * b;
}).done(function( result ) {
            console.log("result = " + result);
}).then(function( a, b ) {
            return a * b;
}).done(function( result ) {
            console.log("result = " + result);
});
defer.resolve( 2, 3 );

在jQuery 1.8版本之前,上面代码的结果是:

复制代码 代码如下:

result = 2
result = 2
result = 2

在jQuery 1.8版本之后,返回结果是

复制代码 代码如下:

result = 2
result = 6
result = NaN

这一点需要特别引起注意。

复制代码 代码如下:

$.ajax( url1, { dataType: "json" } )
.then(function( data ) {
    return $.ajax( url2, { data: { user: data.userId } } );
}).done(function( data ) {
  // 从url2获取的数据
});

上面代码最后那个done方法,处理的是从url2获取的数据,而不是从url1获取的数据。

利用then()会修改返回值这个特性,我们可以在调用其他回调函数之前,对前一步操作返回的值进行处理。

复制代码 代码如下:

var post = $.post("/echo/json/")
    .then(function(p){
        return p.firstName;
    });
post.done(function(r){ console.log(r); });

上面代码先使用then()方法,从返回的数据中取出所需要的字段(firstName),所以后面的操作就可以只处理这个字段了。

有时,Ajax操作返回json字符串里面有一个error属性,表示发生错误。这个时候,传统的方法只能是通过done()来判断是否发生错误。通过then()方法,可以让deferred对象调用fail()方法。

复制代码 代码如下:

var myDeferred = $.post('/echo/json/', {json:JSON.stringify({'error':true})})
    .then(function (response) {
            if (response.error) {
                return $.Deferred().reject(response);
            }
            return response;
        },function () {
            return $.Deferred().reject({error:true});
        }
    );
myDeferred.done(function (response) {
        $("#status").html("Success!");
    }).fail(function (response) {
        $("#status").html("An error occurred");
    });

always()

always()也是指定回调函数,不管是resolve或reject都要调用。

pipe方法

pipe方法接受一个函数作为参数,表示在调用then方法、done方法、fail方法、always方法指定的回调函数之前,先运行pipe方法指定的回调函数。它通常用来对服务器返回的数据做初步处理。

promise对象

大多数情况下,我们不想让用户从外部更改deferred对象的状态。这时,你可以在deferred对象的基础上,返回一个针对它的promise对象。我们可以把后者理解成,promise是deferred的只读版,或者更通俗地理解成promise是一个对将要完成的任务的承诺。

你可以通过promise对象,为原始的deferred对象添加回调函数,查询它的状态,但是无法改变它的状态,也就是说promise对象不允许你调用resolve和reject方法。

复制代码 代码如下:

function getPromise(){
    return $.Deferred().promise();
}
try{
    getPromise().resolve("a");
} catch(err) {
    console.log(err);
}

上面的代码会出错,显示TypeError {} 。

jQuery的ajax() 方法返回的就是一个promise对象。此外,Animation类操作也可以使用promise对象。

复制代码 代码如下:

var promise = $('div.alert').fadeIn().promise();

$.when()方法

$.when()接受多个deferred对象作为参数,当它们全部运行成功后,才调用resolved状态的回调函数,但只要其中有一个失败,就调用rejected状态的回调函数。它相当于将多个非同步操作,合并成一个。

复制代码 代码如下:

$.when(
    $.ajax( "/main.php" ),
    $.ajax( "/modules.php" ),
    $.ajax( "/lists.php" )
).then(successFunc, failureFunc);

上面代码表示,要等到三个ajax操作都结束以后,才执行then方法指定的回调函数。

when方法里面要执行多少个操作,回调函数就有多少个参数,对应前面每一个操作的返回结果。

复制代码 代码如下:

$.when(
    $.ajax( "/main.php" ),
    $.ajax( "/modules.php" ),
    $.ajax( "/lists.php" )
).then(function (resp1, resp2, resp3){
    console.log(resp1);
    console.log(resp2);
    console.log(resp3);
});

上面代码的回调函数有三个参数,resp1、resp2和resp3,依次对应前面三个ajax操作的返回结果。

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

复制代码 代码如下:

$.when({testing: 123}).done(function (x){
  console.log(x.testing); // "123"
});

上面代码中指定的回调函数,将在when方法后面立即运行。

利用这个特点,我们可以写一个具有缓存效果的异步操作函数。也就是说,第一次调用这个函数的时候,将执行异步操作,后面再调用这个函数,将会返回缓存的结果。

复制代码 代码如下:

function maybeAsync( num ) {
  var dfd = $.Deferred();
  if ( num === 1 ) {
    setTimeout(function() {
      dfd.resolve( num );
    }, 100);
    return dfd.promise();
  }
  return num;
}
$.when(maybeAsync(1)).then(function (resp){
  $('#target').append('<p>' + resp + '</p>');
});
$.when(maybeAsync(0)).then(function (resp){
  $('#target').append( '<p>' + resp + '</p>');
});

上面代码表示,如果maybeAsync函数的参数为1,则执行异步操作,否则立即返回缓存的结果。

实例

wait方法

我们可以用deferred对象写一个wait方法,表示等待多少毫秒后再执行。

复制代码 代码如下:

$.wait = function(time) {
  return $.Deferred(function(dfd) {
    setTimeout(dfd.resolve, time);
  });
}

使用方法如下:

复制代码 代码如下:

$.wait(5000).then(function() {
  alert("Hello from the future!");
});

改写setTimeout方法

在上面的wait方法的基础上,还可以改写setTimeout方法,让其返回一个deferred对象。

复制代码 代码如下:

function doSomethingLater(fn, time) {
  var dfd = $.Deferred();
  setTimeout(function() {
    dfd.resolve(fn());
  }, time || 0);
  return dfd.promise();
}
var promise = doSomethingLater(function (){
  console.log( '已经延迟执行' );
}, 100);

澳门金莎娱乐手机版 ,自定义操作使用deferred接口

我们可以利用deferred接口,使得任意操作都可以用done()和fail()指定回调函数。

复制代码 代码如下:

Twitter = {
  search:function(query) {
    var dfr = $.Deferred();
    $.ajax({
     url:"",
     data:{q:query},
     dataType:'jsonp',
     success:dfr.resolve
    });
    return dfr.promise();
  }
}

使用方法如下:

复制代码 代码如下:

Twitter.search('intridea').then(function(data) {
  alert(data.results[0].text);
});

deferred对象的另一个优势是可以附加多个回调函数。

复制代码 代码如下:

function doSomething(arg) {
  var dfr = $.Deferred();
  setTimeout(function() {
    dfr.reject("Sorry, something went wrong.");
  });
  return dfr;
}
doSomething("uh oh").done(function() {
  alert("Won't happen, we're erroring here!");
}).fail(function(message) {
  alert(message)
});

Deferred对象简史

Deferred对象是在 jQuery 1.5 中引入的,该对象提供了一系列的方法,可以将多个回调函数注册进一个回调队列里、调用回调队列,以及将同步或异步函数执行结果的成功还是失败传递给对应的处理函数。从那以后,Deferred 对象就成了讨论的话题, 其中不乏批评意见,这些观点也一直在变化。一些典型的批评的观点如《你并没有理解 Promise 》和《论 Javascript 中的 Promise 以及 jQuery 是如何把它搞砸的》。

Promise 对象 是和 Deferred 对象一起作为 jQuery 对 Promise 的一种实现。在 jQuery1.x 和 2.x 版本中, Deferred 对象遵守的是《CommonJS Promises 提案》中的约定,而 ECMAScript 原生 promises 方法的建立基础《Promises/A+ 提案》也是以这一提案书为根基衍生而来。所以就像我们一开始提到的,之所以 Deferred 对象没有遵循《Promises/A+ 提案》,是因为那时后者根本还没被构想出来。

由于 jQuery 扮演的先驱者的角色以及后向兼容性问题,jQuery1.x 和 2.x 里 promises 的使用方式和原生 Javascript 的用法并不一致。此外,由于 jQuery 自己在 promises 方面遵循了另外一套提案,这导致它无法兼容其他实现 promises 的库,比如 Q library。

不过即将到来的 jQuery 3 改进了 同原生 promises(在 ECMAScript2015 中实现)的互操作性。虽然为了向后兼容,Deferred 对象的主要方法之一(then())的方法签名仍然会有些不同,但行为方面它已经同 ECMAScript 2015 标准更加一致。

jquery的实例对象与jquery的全局对象在用法上有什不同

{ this.id = sId; //函数内部的 this 是这个函数的实例 } 用 prototype对象,这个对象可以用 jQuery 的各种函数。 $('body a').click(function(  

jQuery中的回调函数

举一个例子来理解为什么我们需要用到 Deferred对象。使用 jQuery 时,经常会用到它的 ajax 方法执行异步的数据请求操作。我们不妨假设你在开发一个页面,它能够发送 ajax 请求给 GitHub API,目的是读取一个用户的 Repository 列表、定位到最近更新一个 Repository,然后找到第一个名为“README.md”的文件并获取该文件的内容。所以根据以上描述,每一个请求只有在前一步完成后才能开始。换言之,这些请求必须依次执行

上面的描述可以转换成伪代码如下(注意我用的并不是真正的 Github API):

JavaScript

var username = 'testuser'; var fileToSearch = 'README.md'; $.getJSON('' + username + '/repositories', function(repositories) { var lastUpdatedRepository = repositories[0].name; $.getJSON('' + username + '/repository/' + lastUpdatedRepository + '/files', function(files) { var README = null; for (var i = 0; i < files.length; i++) { if (files[i].name.indexOf(fileToSearch) >= 0) { README = files[i].path; break; } } $.getJSON('' + username + '/repository/' + lastUpdatedRepository + '/file/' + README + '/content', function(content) { console.log('The content of the file is: ' + content); }); }); });

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
var username = 'testuser';
var fileToSearch = 'README.md';
 
$.getJSON('https://api.github.com/user/' + username + '/repositories', function(repositories) {
  var lastUpdatedRepository = repositories[0].name;
 
$.getJSON('https://api.github.com/user/' + username + '/repository/' + lastUpdatedRepository + '/files', function(files) {
    var README = null;
 
for (var i = 0; i < files.length; i++) {
      if (files[i].name.indexOf(fileToSearch) >= 0) {
        README = files[i].path;
 
break;
      }
    }
 
$.getJSON('https://api.github.com/user/' + username + '/repository/' + lastUpdatedRepository + '/file/' + README + '/content', function(content) {
      console.log('The content of the file is: ' + content);
    });
  });
});

如你所见,使用回调函数的话,我们需要反复嵌套来让 ajax 请求按照我们希望的顺序执行。当代码里出现许多嵌套的回调函数,或者有很多彼此独立但需要将它们同步的回调时,我们往往把这种情形称作“回调地狱 ( callback hell )“。

为了稍微改善一下,你可以从我创建的匿名函数中提取出命名函数。但这帮助并不大,因为我们还是在回调的地狱中,依旧面对着回调嵌套和同步的难题。这时是 DeferredPromise对象上场的时候了。

jQuery对象问题

第一个是创建了一个validator对象,validator是这个对象的引用
第二个是在this[0]这个DOM对象上附上一个变量,名叫validator,这个对象的值就是第一行的那个validator,也就是刚刚创建的validator对象。
以后通过this[0]这个DOM对象就可以获取到validator这个对象了。  

deferred对象是jQuery对Promises接口的实现。它是非同步操作的通用接口,可以被看作是一个等待完成的任务...

Deferred和Promise对象

Deferred 对象可以被用来执行异步操作,例如 Ajax 请求和动画的实现。在 jQuery 中,Promise对象是只能由Deferred对象或 jQuery 对象创建。它拥有 Deferred 对象的一部分方法:always(),done(), fail(), state()then()。我们在下一节会讲到这些方法和其他细节。

如果你来自于原生 Javascript 的世界,你可能会对这两个对象的存在感到迷惑:为什么 jQuery 有两个对象(DeferredPromise)而原生JS 只有一个(Promise)? 在我著作的书《jQuery 实践(第三版)》里有一个类比,可以用来解释这个问题。

Deferred对象通常用在从异步操作返回结果的函数里(返回结果可能是 error,也可能为空)——即结果的生产者函数里。而返回结果后,你不想让读取结果的函数改变 Deferred 对象的状态(译者注:包括 Resolved 解析态,Rejected 拒绝态),这时就会用到 promise 对象——即 Promise 对象总在异步操作结果的消费者函数里被使用。

为了理清这个概念,我们假设你需要实现一个基于 promise 的timeout()函数(在本文稍后会展示这个例子的代码)。你的函数会等待指定的一段时间后返回(这里没有返回值),即一个生产者函数而这个函数的对应消费者们并不在乎操作的结果是成功(解析态 resolved)还是失败(拒绝态 rejected),而只关心他们需要在 Deferred 对象的操作成功、失败,或者收到进展通知后紧接着执行一些其他函数。此外,你还希望能确保消费者函数不会自行解析或拒绝 Deferred对象。为了达到这一目标,你必须在生产者函数timeout()中创建 Deferred 对象,并只返回它的 Promise 对象,而不是 Deferred对象本身。这样一来,除了timeout()函数之外就没有人能够调用到resolve()reject()进而改变 Deferred 对象的状态了。

在这个 StackOverflow 问题 里你可以了解到更多关于 jQuery 中 Deferred 和 Promise 对象的不同。

既然你已经了解里这两个对象,让我们来看一下它们都包含哪些方法。

Deferred对象的方法

Deferred对象相当灵活并提供了你可能需要的所有方法,你可以通过调用 jQuery.Deferred() 像下面一样创建它:

JavaScript

var deferred = jQuery.Deferred();

1
var deferred = jQuery.Deferred();

或者,使用 $作为 jQuery 的简写:

JavaScript

var deferred = $.Deferred();

1
var deferred = $.Deferred();

创建完 Deferred对象后,就可以使用它的一系列方法。处了已经被废弃的 removed 方法外,它们是:

  • always(callbacks[, callbacks, ..., callbacks]): 添加在该 Deferred 对象被解析或被拒绝时调用的处理函数
  • done(callbacks[, callbacks, ..., callbacks]): 添加在该 Deferred 对象被解析时调用的处理函数
  • fail(callbacks[, callbacks, ..., callbacks]): 添加在该 Deferred 对象被拒绝时调用的处理函数
  • notify([argument, ..., argument]):调用 Deferred 对象上的 progressCallbacks 处理函数并传递制定的参数
  • notifyWith(context[, argument, ..., argument]): 在制定的上下文中调用 progressCallbacks 处理函数并传递制定的参数。
  • progress(callbacks[, callbacks, ..., callbacks]): 添加在该 Deferred 对象产生进展通知时被调用的处理函数。
  • promise([target]): 返回 Deferred 对象的 promise 对象。
  • reject([argument, ..., argument]): 拒绝一个 Deferred 对象并以指定的参数调用所有的failCallbacks处理函数。
  • rejectWith(context[, argument, ..., argument]): 拒绝一个 Deferred 对象并在指定的上下文中以指定参数调用所有的failCallbacks处理函数。
  • resolve([argument, ..., argument]): 解析一个 Deferred 对象并以指定的参数调用所有的 doneCallbackswith 处理函数。
  • resolveWith(context[, argument, ..., argument]): 解析一个 Deferred 对象并在指定的上下文中以指定参数调用所有的doneCallbacks处理函数。
  • state(): 返回当前 Deferred 对象的状态。
  • then(resolvedCallback[, rejectedCallback[, progressCallback]]): 添加在该 Deferred 对象被解析、拒绝或收到进展通知时被调用的处理函数

从以上这写方法的描述中,我想突出强调一下 jQuery 文档和 ECMAScript 标准在术语上的不同。在 ECMAScript 中, 不论一个 promise 被完成 (fulfilled) 还是被拒绝 (rejected),我们都说它被解析 (resolved) 了。然而在 jQuery 的文档中,被解析这个词指的是 ECMAScript 标准中的完成 (fulfilled) 状态。

由于上面列出的方法太多, 这里无法一一详述。不过在下一节会有几个展示 DeferredPromise用法的示例。第一个例子中我们会利用Deferred 对象重写“ jQuery 的回调函数”这一节的代码。第二个例子里我会阐明之前讨论的生产者–消费者这个比喻。

利用 Deferred 依次执行 Ajax 请求

这一节我会利用Deferred对象和它提供的方法使“jQuery 的回调函数”这一节的代码更具有可读性。但在一头扎进代码之前,让我们先搞清楚一件事:在 Deferred 对象现有的方法中,我们需要的是哪些。

根据我们的需求及上文的方法列表,很明显我们既可以用 done()也可以通过 then()来处理操作成功的情况,考虑到很多人已经习惯了使用JS 的原生 Promise对象,这个示例里我会用 then()方法来实现。要注意 then()done()这两者之间的一个重要区别是 then()能够把接收到的值通过参数传递给后续的 then(),done(),fail()progress()调用。

所以最后我们的代码应该像下面这样:

JavaScript

var username = 'testuser'; var fileToSearch = 'README.md'; $.getJSON('' + username + '/repositories') .then(function(repositories) { return repositories[0].name; }) .then(function(lastUpdatedRepository) { return $.getJSON('' + username + '/repository/' + lastUpdatedRepository + '/files'); }) .then(function(files) { var README = null; for (var i = 0; i < files.length; i++) { if (files[i].name.indexOf(fileToSearch) >= 0) { README = files[i].path; break; } } return README; }) .then(function(README) { return $.getJSON('' + username + '/repository/' + lastUpdatedRepository + '/file/' + README + '/content'); }) .then(function(content) { console.log(content); });

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
var username = 'testuser';
var fileToSearch = 'README.md';
 
$.getJSON('https://api.github.com/user/' + username + '/repositories')
  .then(function(repositories) {
    return repositories[0].name;
  })
  .then(function(lastUpdatedRepository) {
    return $.getJSON('https://api.github.com/user/' + username + '/repository/' + lastUpdatedRepository + '/files');
  })
  .then(function(files) {
    var README = null;
 
for (var i = 0; i < files.length; i++) {
      if (files[i].name.indexOf(fileToSearch) >= 0) {
        README = files[i].path;
 
break;
      }
    }
 
return README;
  })
  .then(function(README) {
    return $.getJSON('https://api.github.com/user/' + username + '/repository/' + lastUpdatedRepository + '/file/' + README + '/content');
  })
  .then(function(content) {
    console.log(content);
  });

如你所见,由于我们能够把整个操作拆分成同在一个缩进层级的各个步骤,这段代码的可读性已经显著提高了。

本文由金沙澳门官网网址发布于前端知识,转载请注明出处:jQuery的Deferred对象概述,jQuery之Deferred对象详整

关键词: