成人国产在线小视频_日韩寡妇人妻调教在线播放_色成人www永久在线观看_2018国产精品久久_亚洲欧美高清在线30p_亚洲少妇综合一区_黄色在线播放国产_亚洲另类技巧小说校园_国产主播xx日韩_a级毛片在线免费

資訊專欄INFORMATION COLUMN

Javascript異步編程-延遲對象篇

callmewhy / 711人閱讀

摘要:上篇文章中講到,使用的方法操作請求,會受到回調(diào)函數(shù)嵌套的問題。第一次回調(diào)第二次回調(diào)內(nèi)部實(shí)現(xiàn)上,和都是基于實(shí)現(xiàn)的對于多個(gè)同時(shí)請求,共同執(zhí)行同一個(gè)回調(diào)函數(shù)這一點(diǎn)上,有一個(gè)方法,接受多個(gè)對象實(shí)例,同時(shí)執(zhí)行。

上篇文章中講到,使用jquery的ajax方法操作ajax請求,會受到回調(diào)函數(shù)嵌套的問題。當(dāng)然,jquery團(tuán)隊(duì)也發(fā)現(xiàn)了這個(gè)問題,在2011年,也就是jquery 1.5版本之后,jQuery.Deferred對象為解決這類問題應(yīng)運(yùn)而出。之后,zapto等框架也推出相同api的deferred對象,來進(jìn)行異步操作。

在jquery 1.5 版本之后,ajax請求的內(nèi)部實(shí)現(xiàn)被重寫。$.ajax方法返回的不再是一個(gè)jqXHR對象,而是一個(gè)Deferred對象。

使用jquery 1.5版本之后的代碼,可以用下面的方法進(jìn)行一次ajax請求。

// 前提引入jquery
var fetchData = function (url) {
    return $.ajax({
        type: "get",
        url: url
    });
}

這樣一次請求的內(nèi)容就已經(jīng)完成,$.ajax返回一個(gè)$.Deferred對象,那么我們就可以使用$.Deferred對象的api進(jìn)行一些異步操作。

出于篇幅,這里只簡單進(jìn)行介紹.done,.fail,.then$.when這三個(gè)方法。

對于每一個(gè)$.Deferred對象來說,實(shí)例有多個(gè)方法,其中done方法代表異步完成時(shí)執(zhí)行的方法,fail代表異步失敗時(shí)執(zhí)行的方法,這兩個(gè)方法同時(shí)仍舊返回一個(gè)$.Deferred對象的實(shí)例。

繼續(xù)上面的ajax操作,我們可以這樣寫成功和失敗的回調(diào):

// fetchData 接上

fetchData()        //執(zhí)行函數(shù)返回一個(gè)Deferred對象實(shí)例
    .done()        //接受一個(gè)函數(shù),ajax請求成功調(diào)用
    .fail()        //接受一個(gè)函數(shù),ajax請求失敗調(diào)用
    .done()        //第二個(gè)成功狀態(tài)的回調(diào)方法
    .fail()

同樣的對于.then方法,接受兩個(gè)函數(shù),第一個(gè)代表成功時(shí)執(zhí)行的方法,第二個(gè)代表失敗時(shí)的執(zhí)行方法。同樣的,它也返回一個(gè)deferred對象實(shí)例。意味著也能進(jìn)行連綴調(diào)用。

fetchData()
    .then(successFn, errorFn)        //第一次回調(diào)
    .then(successFn, errorFn)        //第二次回調(diào)

內(nèi)部實(shí)現(xiàn)上,.done 和 .fail 都是基于 .then實(shí)現(xiàn)的

fetchData()                            fetchData()
    .done(successFn)    <===>            .then(successFn, null)
    .fail(errorFn)      <===>            .then(null, errorFn)

對于多個(gè)ajax同時(shí)請求,共同執(zhí)行同一個(gè)回調(diào)函數(shù)這一點(diǎn)上,jquery有一個(gè)$.when方法,接受多個(gè)Deferred對象實(shí)例,同時(shí)執(zhí)行。

var fetchData = function (url) {
    return $.ajax({
        type: "get",
        url: url
    });
}

var fetchData1 = fetchData("/path/to/data1");
var fetchData2 = fetchData("/path/to/data2");

$.when(fetchData1, fetchData2, function (data1, data2) {
    // fetchData1 響應(yīng)為data1
    // fetchData2 響應(yīng)為data2
})

完美解決了開發(fā)中的異步問題。

上面的$.ajax只是在$.deferred對象上封裝了一層ajax操作。實(shí)際上,真正的$.Deferred對象是這樣調(diào)用的:

function printA () {
    var deferred = new $.Deferred();
    setTimeout(function () {
        console.log("A");
        deferred.resolve(" is done.");
    }, 1000);
    return deferred;
}

function printB (msg) {
    var deferred = new $.Deferred();
    setTimeout(function () {
        console.log("B" + msg);
        deferred.resolve();
    }, 1000);
    return deferred;
}

printA()
    .then(printA)
    .then(printB)

每個(gè)函數(shù)維護(hù)一個(gè)Deferred對象,在每一個(gè)具有異步操作的函數(shù)執(zhí)行成功后,指示全局deferred對象執(zhí)行下一個(gè)函數(shù),達(dá)到異步的效果。

新建完成$.Deferred實(shí)例deferred之后,調(diào)用deferred.resolve()代表成功完成響應(yīng),deferred.reject()即代表調(diào)用失敗響應(yīng)。

詳細(xì)解釋源碼請參見另一篇文章,這里我們主要寫一下這種調(diào)用方式實(shí)現(xiàn)的tiny版。

首先我們寫一個(gè)Callback對象維護(hù)我們的回調(diào)函數(shù)隊(duì)列

var Callbacks = function () {
    function Callbacks () {
        this.callbacks = [];
    }
    Callbacks.prototype.add = function (fn) {
        this.callbacks.add(fn);
        return this;
    }
    Callbacks.prototype.fire = function () {
        var len = this.callbacks.length;
        if(len) {
            this.callbacks.unshift()();
        }
    }
    return Callbacks;
}

這段代碼邏輯很簡單,Callbacks對象有兩個(gè)方法,分別是add和fire,調(diào)用add則向當(dāng)前的callbacks數(shù)組內(nèi)新增一個(gè)function。fire方法,則從Callbacks中提取最前的一個(gè)callback,并執(zhí)行它。

對于Deferred對象,我們至少需要resolve和reject兩個(gè)方法。進(jìn)行成功和失敗的調(diào)用。并且能夠進(jìn)行鏈?zhǔn)秸{(diào)用。

var Deferred = function () {
    this.successCbs = new Callbacks();
    this.errorCbs = new Callbacks();
}
Deferred.prototype.then = function (successCb, errorCb) {
    this.successCbs.add(successCb);
    this.errorCbs.add(errorCb);
    return this;
}
Deferred.prototype.resolve = function () {
    this.successCbs.fire();
    return this;
}
Deferred.prototype.reject = function () {
    this.errorCbs.fire();
    return this;
}

這樣簡單完成之后,我們新建一個(gè)Deferred實(shí)例,就能夠通過鏈?zhǔn)秸{(diào)用的方式進(jìn)行異步操作。

var deferred = new Deferred();
function printA() {
    setTimeout(function () {
        console.log("A");
        deferred.resolve();
    }, 1000);
    return deferred;
}
function printB() {
    setTimeout(function () {
        console.log("B");
        deferred.resolve();
    }, 1000);
}

printA()
    .then(printB)
    .then(printA)

同樣的,我們可以封裝一個(gè)自制tiny-Deferred對象的tiny-ajax方法。

var ajax = function (options) {
    var xhrOptions = {
        type: options.type || "get",
        url: options.url || "/default/path",
        async: options.async || true
    };
    var deferred = new Deferred();
    var xhr = new XHRHttpRequest();
    xhr.open(xhrOptions.type, xhrOptions.url, xhrOptions.async);
    xhr.onload = function (result) {
        deferred.resolve(result);
    }
    xhr.onerror = function ()
    xhr.send();
    return deferred;
}

具體源代碼開源在Github上,歡迎pr和issuses。

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

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

相關(guān)文章

  • Javascript 異步編程-基礎(chǔ)

    摘要:在前端這個(gè)領(lǐng)域里面,請求非常常見,相信每一個(gè)前端都寫過下面的代碼前提引入上面這段代碼中的和被稱為回調(diào)函數(shù)。多個(gè)請求希望有一個(gè)共同的回調(diào)響應(yīng)繼續(xù)使用最初的方法,假設(shè)有多個(gè)請求,希望在全部完成后執(zhí)行回調(diào)函數(shù)。異步編程延遲對象篇 在前端這個(gè)領(lǐng)域里面,ajax請求非常常見,相信每一個(gè)前端er都寫過下面的代碼: // 前提引入jquery $.ajax({ type: get, ...

    huaixiaoz 評論0 收藏0
  • JavaScript異步編程原理

    摘要:一異步編程原理顯然,上面這種方式和銀行取號等待有些類似,只不過銀行取號我們并不知道上一個(gè)人需要多久才會完成。下面來探討下中的異步編程原理。 眾所周知,JavaScript 的執(zhí)行環(huán)境是單線程的,所謂的單線程就是一次只能完成一個(gè)任務(wù),其任務(wù)的調(diào)度方式就是排隊(duì),這就和火車站洗手間門口的等待一樣,前面的那個(gè)人沒有搞定,你就只能站在后面排隊(duì)等著。在事件隊(duì)列中加一個(gè)延時(shí),這樣的問題便可以得到緩解...

    lidashuang 評論0 收藏0
  • javascript異步編程詳解

    摘要:在服務(wù)器端,異步模式甚至是唯一的模式,因?yàn)閳?zhí)行環(huán)境是單線程的,如果允許同步執(zhí)行所有請求,服務(wù)器性能會急劇下降,很快就會失去響應(yīng)。第三是,捕捉不到他的錯(cuò)誤異步編程方法回調(diào)函數(shù)這是異步編程最基本的方法。 前言 你可能知道,Javascript語言的執(zhí)行環(huán)境是單線程(single thread)。所謂單線程,就是指一次只能完成一件任務(wù)。如果有多個(gè)任務(wù),就必須排隊(duì),前面一個(gè)任務(wù)完成,再執(zhí)行后面...

    huangjinnan 評論0 收藏0
  • 前端_JavaScript

    摘要:為此決定自研一個(gè)富文本編輯器。例如當(dāng)要轉(zhuǎn)化的對象有環(huán)存在時(shí)子節(jié)點(diǎn)屬性賦值了父節(jié)點(diǎn)的引用,為了關(guān)于函數(shù)式編程的思考作者李英杰,美團(tuán)金融前端團(tuán)隊(duì)成員。只有正確使用作用域,才能使用優(yōu)秀的設(shè)計(jì)模式,幫助你規(guī)避副作用。 JavaScript 專題之惰性函數(shù) JavaScript 專題系列第十五篇,講解惰性函數(shù) 需求 我們現(xiàn)在需要寫一個(gè) foo 函數(shù),這個(gè)函數(shù)返回首次調(diào)用時(shí)的 Date 對象,注意...

    Benedict Evans 評論0 收藏0
  • 搞懂 JavsScript 異步 —? 事件輪詢

    showImg(https://segmentfault.com/img/bVbjYU7?w=2000&h=1333); 想閱讀更多優(yōu)質(zhì)文章請猛戳GitHub博客,一年百來篇優(yōu)質(zhì)文章等著你! JavsScript 是一門單線程的編程語言,這就意味著一個(gè)時(shí)間里只能處理一件事,也就是說 JavaScript 引擎一次只能在一個(gè)線程里處理一條語句。 雖然單線程簡化了編程代碼,因?yàn)槟悴槐靥珦?dān)心并發(fā)引出的問...

    adam1q84 評論0 收藏0

發(fā)表評論

0條評論

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