jQuery的異步機制


異步方式的概述

  • 通過事件達到異步操作
  • 通過我們最熟悉的回調(diào)
  • 類promise的方式

首先我們注意到1.5版本前后的jquery有一個重要的不同

//before 1.5
var option={
    type:'GET',
    url:'...',
    success:function(){..},
    fail:function(){..},
    complete:function(){..}
};
$.ajax(option);
//after 1.5
$.ajax(option)
    .done(function(){..})
    .fail(function(){..})
    .progress(function(){..})
    .always(function(){..})
            

1.5版本之后變成了優(yōu)美的鏈式調(diào)用,并且可以對同一事件增加多個回調(diào)函數(shù),原因是原生的xhr對象換成了jqxhr對象,里面有什么魔法呢?

從promise講起

promise在javascript編程世界里可以說是大名鼎鼎,下面這段代碼給出了它的簡單用法。

promise(function(){..}).
then([successhandler1,successhandler2,..],
     [failhandler1,failhandler2,...]);

promise為我們呈現(xiàn)出了異步編程的一種新模式,但它還不夠漂亮,接下來我們看一看jQuery引入的deferred。

jQuery的Deferred

創(chuàng)建Deferred對象

var de=$.Deferred();//空的Deferred對象
$.Deferred(function(){..}).
  done(function(){..});
//會直接執(zhí)行里面的function并返回一個Deferred對象
function tmp(defer){
    ....
    return defer;
};//這個寫法的含義我們留在后面再講

Deferred的機理

我們可以這樣想,每個deferred對象內(nèi)部有一個隱藏著的狀態(tài)變量,有成功、失敗、執(zhí)行中三種狀態(tài),當(dāng)程序執(zhí)行成功則會把它設(shè)為成功,否則設(shè)為失敗。這里的成功失敗指的是滿足某種設(shè)定條件,并非一般意義上的出錯,即使拋出異常也不認為其失敗。我們可以在程序的運行過程中根據(jù)檢測到的狀態(tài)來決定之后哪些回調(diào)函數(shù)會被執(zhí)行。

設(shè)定狀態(tài)實例

$(function(){
    ....
    if(..) this.resolve(arg1,arg2,..);
    //會執(zhí)行done和always回調(diào),args是傳入回調(diào)的參數(shù)
    //同類函數(shù)this.resolveWith(content,[args..]);content作為回調(diào)函數(shù)中的this
    else this.reject(arg1,arg2,..);
    //執(zhí)行fail和always回調(diào),rejectWith基本同上
    //需要注意的是always也必須狀態(tài)改變才能調(diào)用,若一直處于執(zhí)行狀態(tài),也不會調(diào)用
    ....
    this.notify(args);//調(diào)用progress回調(diào),但必須在狀態(tài)變?yōu)槌晒蚴∏鞍l(fā)起,這里progress不會被調(diào)用
    //notifyWith基本同上
}).fail(..).done(..).progress(..);

還需要注意的是,即使?fàn)顟B(tài)發(fā)生改變了,程序還會繼續(xù)運行。這里所說的成功失敗指的是滿足我們設(shè)定的條件與否,和程序真的運行狀態(tài)無關(guān),done、fail、always返回的依然是原本的deferred對象。

請記住無論什么回調(diào)都是在函數(shù)執(zhí)行完后調(diào)用,函數(shù)執(zhí)行不會被中斷

最后還要注意一點未防止?fàn)顟B(tài)在程序外部被更改,應(yīng)該加上一句
$.Deferred(function(){..}).promise().done(..).fail(..);
但promise返回的不再是原本的Deferred對象了,也不能在外部更改其狀態(tài)了。

強勁的when

看到這里我們可能有一個疑問,如果我們有一系列任務(wù)來決定后來的回調(diào)怎么辦,不用擔(dān)心我們有when。

$.when(defer1,defer2...);
//這時候如果每個defer還要$(func(){..})就很難寫了,所以就回到我們開始介紹的最后一種,利用函數(shù)返回
var defer1=$.Deferred();
var defer2=$.Deferred();
function func1(defer){...return defer;}
function func2(defer){...return defer;}
$.when(func1(defer1),func2(defer2)).done(..).fail(..);
//當(dāng)全部defer成功done才會被調(diào)用,有一個defer失敗fail就會調(diào)用,但無論怎樣一個回調(diào)函數(shù)最多被調(diào)用一次,且不會影響所有函數(shù)的執(zhí)行
var tmp=9;
$.when(tmp).done(..).fail(..);
//當(dāng)when鏈里面全部不是defer變量時會直接執(zhí)行done回調(diào),注意是全部,有defer變量會跳過非defer,回調(diào)取決于defer
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

  • Promise 的含義 一句話概括一下promise的作用:可以將異步操作以同步操作的流程表達出來,避免了層層嵌套...
    雪萌萌萌閱讀 5,657評論 0 7
  • 抽象來說,deferreds 可以理解為表示需要長時間才能完成的耗時操作的一種方式,相比于阻塞式函數(shù)它們是異步的,...
    北方蜘蛛閱讀 1,650評論 1 5
  • 一、什么是deferred對象? 開發(fā)網(wǎng)站的過程中,我們經(jīng)常遇到某些耗時很長的javascript操作。其中,既有...
    壯哉我大前端閱讀 308評論 0 1
  • jQuery的deferred對象詳解 作者:阮一峰 一、什么是deferred對象? 開發(fā)網(wǎng)站的過程中,我們經(jīng)常...
    JamHsiao_aaa4閱讀 356評論 0 0
  • 當(dāng)自己的大學(xué)生涯過了兩個月之后,一切穩(wěn)定安然,和室友相處融洽。突然覺得少了一些什么?想有個能陪我一起聊天,...
    紫月天魅閱讀 325評論 3 2

友情鏈接更多精彩內(nèi)容