亚洲中字慕日产2020,大陆极品少妇内射AAAAAA,无码av大香线蕉伊人久久,久久精品国产亚洲av麻豆网站

資訊專欄INFORMATION COLUMN

Promise介紹--Deferred及jQuery篇

Darkgel / 1498人閱讀

摘要:我們稱為回調(diào)對象,它內(nèi)部會維護(hù)一個數(shù)組,我們可以向其中添加若干個回調(diào)函數(shù),然后在某一條件下觸發(fā)執(zhí)行。第一次之后,再次新的回調(diào)函數(shù)時,自動執(zhí)行回調(diào)。當(dāng)前面的回調(diào)函數(shù)返回時,終止后面的回調(diào)繼續(xù)執(zhí)行。

最近懶癌發(fā)作,說好的系列文章,寫了一半,一直懶得寫,今天補(bǔ)上一篇。

Deferred

我們在使用promise對象時,總會提到一個與它關(guān)系密切的對象——Deferred。其實(shí)Deferred沒什么內(nèi)容可講的,其實(shí)很簡單。

它包含一個promise對象

它可以改變對應(yīng)的promise的狀態(tài)

簡單的實(shí)現(xiàn)如下:

class Deferred{
    constructor(){
        let defer = {};
        defer.promise = new Promise((resolve, reject)=>{
            defer.resolve = resolve;
            defer.reject = reject;
        })
        return defer;
    }
}

我們知道promise對象內(nèi)部的狀態(tài),本身是在創(chuàng)建對象時傳入的函數(shù)內(nèi)控制,外部是訪問不到的,Deferred對象在它的基礎(chǔ)上包裝了一層,并提供了兩個在外部改變它狀態(tài)的方法。

用法其實(shí)在Promise介紹--規(guī)范篇中的例子內(nèi),多處使用到了,這里就不再贅述??傆X得文章寫這么點(diǎn)兒,就顯得太水了。。所以借此,講講jQuery中的實(shí)現(xiàn)。

jQuery中還有一個靜態(tài)方法$.Callbacks(),由于$.Deferred()強(qiáng)依賴它,所以我們先從它開刀。

$.Callbacks()

$.Callbacks()我們稱為回調(diào)對象,它內(nèi)部會維護(hù)一個數(shù)組,我們可以向其中添加若干個回調(diào)函數(shù),然后在某一條件下觸發(fā)執(zhí)行。

有幾個方法從名字我們就知道它的作用是什么,add向數(shù)組內(nèi)部添加一個回調(diào)函數(shù),empty清空數(shù)組,fire觸發(fā)回調(diào)函數(shù),has數(shù)組中是否已經(jīng)添加某回調(diào)函數(shù),remove從數(shù)組中刪除某回調(diào)函數(shù)。

fireWith函數(shù)接收兩個參數(shù),第一個是回調(diào)函數(shù)執(zhí)行的上下文,第二個是回傳給回調(diào)函數(shù)的參數(shù)。fire中其實(shí)內(nèi)部調(diào)用的就是fireWith,其中第一個參數(shù)傳遞的是this。

其它的幾個函數(shù),都和回調(diào)數(shù)組的狀態(tài)有關(guān)。創(chuàng)建Callbacks對象時,接收一個字符串或者對象作為參數(shù)。其實(shí)內(nèi)部都會轉(zhuǎn)換為對象,這里不贅述,不同字符串表示不同的處理方式,一一介紹。

once :對象只會調(diào)用一次。

let cb = $.Callbacks("once")
function a(){console.log("a")}
function b(){console.log("b")}
cb.add(a)
cb.fire()
cb.add(b)
cb.fire()
// a

第一次fire之后,回調(diào)列表之后不會再次觸發(fā)。

memory : 記住回調(diào)列表的執(zhí)行狀態(tài),如果回調(diào)函數(shù)fire過一次,之后每次add之后,則自動觸發(fā)該回調(diào)。

let cb = $.Callbacks("memory")
function a(){console.log("a")}
function b(){console.log("b")}
cb.add(a)
cb.fire()
// a
cb.add(b)
// b

第一次fire之后,再次add新的回調(diào)函數(shù)b時,自動執(zhí)行回調(diào)b

unique:每一個回調(diào)函數(shù)只可以添加一次。

let cb = $.Callbacks("unique")
function a(){console.log("a")}
function b(){console.log("b")}
cb.add(a)
cb.add(a)
cb.fire()
// a
cb.add(b)
cb.fire()
// a
// b

第一次fire時,只會打印一個a,說明第二個a沒有添加成功,但當(dāng)我們添加b時,是可以添加成功的。

stopOnFalse:當(dāng)前面的回調(diào)函數(shù)返回false時,終止后面的回調(diào)繼續(xù)執(zhí)行。

let cb = $.Callbacks("stopOnFalse")
function a(){console.log("a");return false;}
function b(){console.log("b")}
cb.add(a)
cb.add(b)
cb.fire()
// a

函數(shù)a返回了false,導(dǎo)致函數(shù)b沒有執(zhí)行。

我們再回過頭看$.Callbacks()對象的方法,lock方法表示鎖住回調(diào)數(shù)組,不再執(zhí)行,也就是模式為once時,調(diào)用一次fire后的狀態(tài),即在此之后不可以在此觸發(fā)。如下:

let cb = $.Callbacks()
function a(){console.log("a")}
function b(){console.log("b")}
cb.add(a)
cb.fire()
cb.lock()
cb.add(b)
cb.fire()

lock之后,再次添加函數(shù)b并調(diào)用fire時,不會再次執(zhí)行,與once模式下效果類似。但如果是memory模式,回調(diào)先fire,然后再lock,之后再次add時,新添加的函數(shù)依然會執(zhí)行。

let cb = $.Callbacks("memory")
function a(){console.log("a")}
function b(){console.log("b")}
cb.add(a)
cb.fire()
cb.lock()
cb.add(b)
// a
// b

其實(shí)這種效果和直接創(chuàng)建回調(diào)對象時,參數(shù)設(shè)為once memory是一致的。也就是說,如下代碼與上面效果一致。

let cb = $.Callbacks("once memory")
function a(){console.log("a")}
function b(){console.log("b")}
cb.add(a)
cb.fire()
cb.add(b)
// a
// b

我們發(fā)現(xiàn)這種once memory模式,正好與Promisethen方法添加的回調(diào)很類似。如果promise對象處于pending狀態(tài),則then方法添加的回調(diào)存儲在一個數(shù)組中,當(dāng)promise對象狀態(tài)改變(fire)時,執(zhí)行相應(yīng)的回調(diào),且之后再次通過then方法添加回調(diào)函數(shù),新回調(diào)會立刻執(zhí)行。同時,每一個回調(diào)只能執(zhí)行一次。所以,$.Deferred()內(nèi)部用的正好是once memoryCallbacks。

還有一個函數(shù)叫做disable,它的作用是直接禁用掉這個回調(diào)對象,清空回調(diào)數(shù)組,禁掉fireadd等。

locked用于判斷數(shù)組是否被鎖住,返回truefalse。disabled用于判斷回調(diào)對象是否被警用,同樣返回truefalse。

$.Deferred()

有了以上的基礎(chǔ),我們接下來看看jQuery中,Deferred對象的實(shí)現(xiàn)。我們先看看它都有哪些方法。如圖:

別的方法我們暫且不關(guān)注,我們注意到里面有四個我們比較熟悉的方法,promisereject,resolve。它們和我們前面說的Deferred對象中作用差不多。

jQueryDeferred中有三個添加回調(diào)函數(shù)的方法done,fail,progress,分別對應(yīng)添加promise狀態(tài)為resolved、rejectedpending時的回調(diào),同時對應(yīng)有三個觸發(fā)回調(diào)函數(shù)的方法resolve、rejectnotify

我們接下來看看它內(nèi)部是怎么實(shí)現(xiàn)的。首先為每種狀態(tài)分別創(chuàng)建一個Callbacks對象,如下:

  var tuples = [
      // action, add listener, listener list, final state
     ["resolve", "done", jQuery.Callbacks("once memory"), "resolved"],
     ["reject", "fail", jQuery.Callbacks("once memory"), "rejected"],
     ["notify", "progress", jQuery.Callbacks("memory")]
]

我們發(fā)現(xiàn)done、fail對應(yīng)的回調(diào)對象是once memory,而progress對應(yīng)的是memory。說明通過progress添加的函數(shù),可以多次重復(fù)調(diào)用。

然后定義了一個state用來保存狀態(tài),以及內(nèi)部的一個promise對象。

state = "pending",
promise = {
    state: function() {
        return state;
    },
    always: function() {
        deferred.done(arguments).fail(arguments);
        return this;
    },
    then: function( /* fnDone, fnFail, fnProgress */ ) {
    },

    // Get a promise for this deferred
    // If obj is provided, the promise aspect is added to the object
    promise: function(obj) {
        return obj != null ? jQuery.extend(obj, promise) : promise;
    }
},

接下來會執(zhí)行一個循環(huán),如下:

// Add list-specific methods
jQuery.each(tuples, function(i, tuple) {
    var list = tuple[2],
        stateString = tuple[3];

    // promise[ done | fail | progress ] = list.add
    promise[tuple[1]] = list.add;

    // Handle state
    if (stateString) {
        list.add(function() {

            // state = [ resolved | rejected ]
            state = stateString;

            // [ reject_list | resolve_list ].disable; progress_list.lock
        }, tuples[i ^ 1][4].disable, tuples[2][5].lock);
    }

    // deferred[ resolve | reject | notify ]
    deferred[tuple[0]] = function() {
        deferred[tuple[0] + "With"](this === deferred ? promise : this, arguments);
        return this;
    };
    deferred[tuple[0] + "With"] = list.fireWith;
});

這一段代碼中我們可以看出,done、fail、progress其實(shí)就是addresolve、rejectnotify其實(shí)就是fire,與之對應(yīng)的resolveWithrejectWithnotifyWith其實(shí)就是fireWith。且成功和失敗的回調(diào)數(shù)組中,會預(yù)先添加一個函數(shù),用來設(shè)置promise的狀態(tài)和禁用掉其它狀態(tài)下的回調(diào)對象。

從上面這段代碼中我們也可以看出,添加回調(diào)函數(shù)的方法,都是添加在promise對象上的,而觸發(fā)回調(diào)的方法是添加在deferred對象上的。代碼中會通過如下方法,把promise對象的方法合并到deferred對象上。

promise.promise(deferred);

所以,我們打印一下$.Deferred().promise()。

發(fā)現(xiàn)它確實(shí)比$.Deferred()少了那幾個觸發(fā)回調(diào)的方法。

其它的幾個方法我們簡單說一下,always會同時在成功和失敗的回調(diào)數(shù)組中添加方法。state是查看當(dāng)前promise對象的狀態(tài)。

then方法如下:

then: function( /* fnDone, fnFail, fnProgress */ ) {
    var fns = arguments;
    return jQuery.Deferred(function(newDefer) {
        jQuery.each(tuples, function(i, tuple) {
            var fn = jQuery.isFunction(fns[i]) && fns[i];

            // deferred[ done | fail | progress ] for forwarding actions to newDefer
            deferred[tuple[1]](function() {
                var returned = fn && fn.apply(this, arguments);
                if (returned && jQuery.isFunction(returned.promise)) {
                    returned.promise()
                        .progress(newDefer.notify)
                        .done(newDefer.resolve)
                        .fail(newDefer.reject);
                } else {
                    newDefer[tuple[0] + "With"](
                        this === promise ? newDefer.promise() : this,
                        fn ? [returned] : arguments
                    );
                }
            });
        });
        fns = null;
    }).promise();
}

從代碼中我們可以看出,then方法和規(guī)范中的then方法類似,不過這里多了第三個參數(shù),是用于給progress添加回調(diào)函數(shù),同時返回一個新的promise對象。

pipe是為了向前兼容,它與then是相等的。

$.when()

jQuery中還有一個與之相關(guān)的方法$.when(),它的作用類似于Promise.all()。具體實(shí)現(xiàn)方式基本是新建了一個Deferred對象,然后遍歷所有傳遞進(jìn)去的promise對象。不過添加了progres
的處理??傊鸵?guī)范有很多的不同,大家有興趣的就自己看一下吧。

文章版權(quán)歸作者所有,未經(jīng)允許請勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。

轉(zhuǎn)載請注明本文地址:http://www.ezyhdfw.cn/yun/86653.html

相關(guān)文章

  • jQuery Deferred

    摘要:比較下和也就是說返回值是的一個非狀態(tài)操作的子集,允許我們添加回調(diào),但是不允許我們操作的狀態(tài)。前面說了的返回值是一個新的對象,如果在新的對象上繼續(xù)添加回調(diào)會怎么樣呢我們分兩種情況來看。方法的返回值不是對象的返回值會傳遞給的參數(shù)。 前言 Deferred是從1.5版本引入的一個核心特性之一,主要是為了解決Callback Hell,老生常談的問題,這里就不多贅述了。本文旨在剖析Deferr...

    HollisChuang 評論0 收藏0
  • jquery ajax 方法封裝說明

    摘要:簡要說明前面我寫了一篇方法封裝及文件設(shè)計(jì)文檔,主要用來說明我們在項(xiàng)目中通常會對的方法進(jìn)行進(jìn)一步的封裝處理,便于我們在業(yè)務(wù)代碼中使用。這篇文檔我們主要對封裝的方法進(jìn)行一個簡要說明。 簡要說明 前面我寫了一篇《jquery ajax 方法封裝及 api 文件設(shè)計(jì)》文檔,主要用來說明我們在項(xiàng)目中通常會對 jquery 的 ajax 方法進(jìn)行進(jìn)一步的封裝處理,便于我們在業(yè)務(wù)代碼中使用。從那篇文...

    z2xy 評論0 收藏0
  • jQuery源碼解析Deferred異步對象

    摘要:回調(diào)隊(duì)列對象,用于構(gòu)建易于操作的回調(diào)函數(shù)集合,在操作完成后進(jìn)行執(zhí)行。對象對象,用于管理回調(diào)函數(shù)的多用途列表。如果傳入一個延遲對象,則返回該對象的對象,可以繼續(xù)綁定其余回調(diào),在執(zhí)行結(jié)束狀態(tài)之后也同時調(diào)用其回調(diào)函數(shù)。 在工作中我們可能會把jQuery選擇做自己項(xiàng)目的基礎(chǔ)庫,因?yàn)槠涮峁┝撕啽愕腄OM選擇器以及封裝了很多實(shí)用的方法,比如$.ajax(),它使得我們不用操作xhr和xdr對象,直...

    Coding01 評論0 收藏0
  • jQuery Deferred對象

    摘要:給普通的操作指定回調(diào)函數(shù)對象的最大優(yōu)點(diǎn),就是它把這一套回調(diào)函數(shù)接口,從操作擴(kuò)展到了所有操作。方法用于指定對象狀態(tài)為已失敗時的回調(diào)函數(shù)。執(zhí)行完畢執(zhí)行成功執(zhí)行失敗接收一個或多個對象作為參數(shù),為其指定回調(diào)函數(shù)。 什么是deferred對象 開發(fā)網(wǎng)站的過程中,我們經(jīng)常遇到某些耗時很長的javascript操作。其中,既有異步的操作(比如ajax讀取服務(wù)器數(shù)據(jù)),也有同步的操作(比如遍歷一個大型...

    baoxl 評論0 收藏0
  • 異步 JavaScript 與 Promise

    摘要:為這些回調(diào)函數(shù)分別命名并分離存放可以在形式上減少嵌套,使代碼清晰,但仍然不能解決問題。如果在一個結(jié)束成功或失敗,同前面的說明后,添加針對成功或失敗的回調(diào),則回調(diào)函數(shù)會立即執(zhí)行。 異步? 我在很多地方都看到過異步(Asynchronous)這個詞,但在我還不是很理解這個概念的時候,卻發(fā)現(xiàn)自己常常會被當(dāng)做已經(jīng)很清楚(* ̄? ̄)。 如果你也有類似的情況,沒關(guān)系,搜索一下這個詞,就可以得到大致...

    livem 評論0 收藏0

發(fā)表評論

0條評論

最新活動
閱讀需要支付1元查看
<