国产xxxx99真实实拍_久久不雅视频_高清韩国a级特黄毛片_嗯老师别我我受不了了小说

資訊專欄INFORMATION COLUMN

你所必須掌握的三種異步編程方法callbacks,listeners,promise

boredream / 871人閱讀

摘要:出處你所必須掌握的三種異步編程方法前言都知道,語言運(yùn)行環(huán)境是單線程的,這意味著任何兩行代碼都不能同時運(yùn)行。這也是一種常見的異步編程方式,如設(shè)計(jì)模式中將這種方式稱之為命令模式。這就是我們要介紹的異步編程方法。

出處:你所必須掌握的三種異步編程方法callbacks,listeners,promise

前言

coder都知道,javascript語言運(yùn)行環(huán)境是單線程的,這意味著任何兩行代碼都不能同時運(yùn)行。多任務(wù)同時進(jìn)行時,實(shí)質(zhì)上形成了一個隊(duì)列,當(dāng)隊(duì)列中前一個事件結(jié)束時,才執(zhí)行下一個事件。 如果隊(duì)列中任何一個事務(wù)費(fèi)時太長,則會造成瀏覽器假死,阻塞其他事務(wù)正常進(jìn)行,影響用戶體驗(yàn)。

js中將任務(wù)執(zhí)行分為同步模式和異步模式,上面一種即為同步模式,任何比較花時間的代碼最好設(shè)計(jì)成異步模式。通過異步編程方式,即可以達(dá)到偽多進(jìn)程。常見的異步模式主要有callbaks,listeners(一種觀察者模式),promise,下面我將會詳細(xì)描述三者各自的優(yōu)劣。

Callbacks

這是再常見不過的異步編程方式了,任何前端都寫過這樣的代碼吧:

function callback(){
      console.log("do callbacks");
};
setTimeout(callback,300);

通過這種方式,你可以簡單的實(shí)現(xiàn)異步編程。這里需要注意,這里的300ms只是理想時間,實(shí)際中各瀏覽器略有差異,主要取決于線程中其他任務(wù)所用的時間。這個不具體討論,其中還涉及requestAnimationFrame等。自己可以google。

此方法缺點(diǎn)是什么想必我不說你也知道,如:

function fn1(f){
alert(1);
f();
};
function fn2(f){
alert(2);
f();
};
function fn3(){
alert(3);

};

fn1(function(){ fn2(fn3); });

如果邏輯在復(fù)雜一點(diǎn)呢?恐怖看代碼的人會一頭霧水吧。而promise則可以把這種復(fù)雜的嵌套寫的一看就明白,下面會講到。

Listeners

這也是一種常見的異步編程方式,如:

$elem.on("click",doClick);
function doClick(){
      //do something
};

設(shè)計(jì)模式中將這種方式稱之為命令模式。這種方式的好處是你可以注冊多個事件,待事件觸發(fā)時調(diào)用注冊的函數(shù)。

當(dāng)然這里不僅僅是這種簡單的監(jiān)聽方式,我需要將的是一種更抽象的異步編程方式——listeners。通過觀察者模式,我們用一個數(shù)組來保存事件名稱以及事件綁定的函數(shù)方法,當(dāng)需要觸發(fā)該事件時,我們從數(shù)組中取出之前的注冊的函數(shù)。而EventProxy就是這種方式實(shí)現(xiàn)的,通過on,all注冊,emit觸發(fā)。如:

var ep = EventProxy.create("template", "data", "l10n", function (template, data, l10n) {
  _.template(template, data, l10n);
});

$.get("template", function (template) {
  // something
  ep.emit("template", template);
});
$.get("data", function (data) {
  // something
  ep.emit("data", data);
});
$.get("l10n", function (l10n) {
  // something
  ep.emit("l10n", l10n);
});

下面我用自己的代碼簡單的實(shí)現(xiàn)這種方式

var Observer = {
        _callbacks:{},
        register:function(name,fn,context){
            if(!name){
                return;
            }
            fn = fn || function(){};
            if(!Observer._callbacks[name]){
                var list = Observer._callbacks[name] = [];
            }
            list.push({fn:fn,context:context});
        },
        trigger:function(name){
            var lists = [];
            if(!name){ //觸發(fā)所有
                for(var key in Observer._callbacks){
                    lists.concat(Observer._callbacks[key]);
                }
            }else{ //觸發(fā)指定
                lists = Observer._callbacks[name];
            }
            for(var i = 0,len =lists.length;i

這種模式在于跨模塊異步編程中顯得尤為重要。具體的實(shí)現(xiàn)邏輯剛才已經(jīng)講過,就不具體展開,看代碼注釋即可。

Promise

最后一種方法隆重登場,也是現(xiàn)在討論最多的異步編程方式。

代碼其實(shí)是現(xiàn)實(shí)的歸納總結(jié)并以另外一種方式展現(xiàn),我們有時候看不懂,是因?yàn)閷懘a方式跟現(xiàn)實(shí)有差異。假如代碼邏輯這么寫:

img1.callThisIfLoadedOrWhenLoaded(function() {
  // 加載完成
}).orIfFailedCallThis(function() {
  // 加載失敗
});
// 以及……
whenAllTheseHaveLoaded([img1, img2]).callThis(function(){
    // 全部加載完成
}).orIfSomeFailedCallThis(function(){
    // 一個或多個加載失敗
});

我相信非程序員也能看懂吧。這就是我們要介紹的Promise異步編程方法。現(xiàn)有一些插件庫Q.js, ?when.js ?,wind.js ?,rsvp.js都是類似實(shí)現(xiàn)的,遵守一個通用的、標(biāo)準(zhǔn)化的規(guī)范:Promises/A+,jQuery 有個類似的方法叫?Deferred,但不兼容 Promises/A+ 規(guī)范,于是會有點(diǎn)小問題,使用需謹(jǐn)慎。jQuery 還有一個?Promise 類型,它其實(shí)是 Deferred 的縮減版,所以也有同樣問題。jQuery相關(guān)的后續(xù)我會分章節(jié)逐一講述,這里不做展開。

Promise異步編程總結(jié)起來就是實(shí)現(xiàn)了thenable,說的更直白的一點(diǎn)就是我跟你是好朋友,我可能有事需要你幫忙,你隨時候著吧,有需要我會第一時間通知你。你跟小王也是好哥們,并同樣告訴你需要他幫忙,并第一時間通知他。當(dāng)然你通知他是在我通知你以后。用偽代碼表示:

myself(function(){
          callXiaoLi();
    })
    .then(function(){
         //我是小李,你喊我了,我就去喊小王
         callXiaowang();
    })
    .then(function(){ console.log("我是小王");  });

同樣,下面我們會用簡單的代碼實(shí)現(xiàn)以上邏輯。

/**
 * author by 素人漁夫
 * email:dengxiaoming1217@gmail.com
 * description: 異步編程promise實(shí)現(xiàn)
 */
(function() {
    /*
     * promise
     */
    function EasyPromise() {
        this._callbacks = [];
    };
    EasyPromise.prototype = {
        then: function(func, context) {
            var p;
            if (this._isdone) {
                p = func.apply(context, this.result);
            } else {
                p = new EasyPromise();
                this._callbacks.push(function() {
                    //此時apply context很重要,否則,res中的實(shí)例獲取不到this
                    var res = func.apply(context, arguments);
                    if (res && typeof res.then === "function") {
                        res.then(p.resolve, p);
                    }else{
                        p.resolve(res);
                    };
                });
            }
            return p;
        },
        resolve: function() {
            this.result = arguments;
            this._isdone = true;
            for (var i = 0; i < this._callbacks.length; i++) {
                this._callbacks[i].apply(this.result, arguments);
            }
            this._callbacks = [];
        }
    };
    EasyPromise.when = function() {
        var AllPromises = [].slice.call(arguments, 0)[0];
        var p = new EasyPromise();
        var promiseLen = AllPromises.length;

        var doneParams = {};
        AllPromises.forEach(function(item, index) {
            item.__promise__name = index;
            doneParams[index] = {};
            item.then(checkAllPromiseDone, item);
        });
        var donePromiseCount = 0;

        function checkAllPromiseDone(data) {
            donePromiseCount++;
            doneParams[this.__promise__name] = data;
            if (donePromiseCount == promiseLen) {
                doneParams = makeArray(doneParams);
                p.resolve(doneParams);
            }
        };
        return p;
    };


    if (typeof define !== "undefined") {
        define([], function() {
            return EasyPromise;
        });
    } else if (typeof exports !== "undefined") {
        exports.EasyPromise = EasyPromise;
    } else {
        window.EasyPromise = EasyPromise;
    }
})();

then實(shí)現(xiàn)比較繞,需要解釋一下,如:.then(xx).then()

每次.then時會生成一個新的promise對象, 就是說后一個then是注冊給上一個promise對象的,其出發(fā)條件依賴于上一個.then時生成的promise。

如果上一個.then 最后返回結(jié)果是非promise對象(即沒有then方法),則直接 resolve

如果上一個.then最后返回的結(jié)果是promise對象,那.then生成的promise必須依賴返回結(jié)果中的promise,及內(nèi)層的 promise.then( ".then時生成的promise".resolve)

可能我這么解釋還是沒能解釋很清楚,自己去理解吧。

另外,谷歌瀏覽器已經(jīng)實(shí)現(xiàn)了Promise API。我使用的式chrome?版本 31.0.1650.63。不行你可以在控制臺輸入以下代碼測試:

var p = new Promise(function(resolve,reject){    
    setTimeout(resolve,100);
    setTimeout(reject,300); 
}); 
p.then(function(){ 
  alert("resolve"); 
},function(){ 
  alert("reject");
 });

好了,異步編程的方式就講這么多,我這里只不過是拋磚引玉,并沒有詳細(xì)闡述其api,而是以自己的代碼簡單實(shí)現(xiàn)其原來。這些異步編程方式不僅僅限于瀏覽器環(huán)境,服務(wù)器環(huán)境如nodejs也可使用。比如EventProxy本來就是在nodejs中發(fā)展而來的。

希望通過我的簡單講述能給大家提供幫忙。如果有錯,請幫忙指出,謝謝。

參考:

1.http://www.html5rocks.com/en/tutorials/es6/promises/

2.http://sporto.github.io/blog/2012/12/09/callbacks-listeners-promises/

3.http://www.ruanyifeng.com/blog/2012/12/asynchronous%EF%BC%BFjavascript.html

4.http://javascript.info/tutorial/events-and-timing-depth

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

轉(zhuǎn)載請注明本文地址:http://specialneedsforspecialkids.com/yun/91488.html

相關(guān)文章

  • ES6-7

    摘要:的翻譯文檔由的維護(hù)很多人說,阮老師已經(jīng)有一本關(guān)于的書了入門,覺得看看這本書就足夠了。前端的異步解決方案之和異步編程模式在前端開發(fā)過程中,顯得越來越重要。為了讓編程更美好,我們就需要引入來降低異步編程的復(fù)雜性。 JavaScript Promise 迷你書(中文版) 超詳細(xì)介紹promise的gitbook,看完再不會promise...... 本書的目的是以目前還在制定中的ECMASc...

    mudiyouyou 評論0 收藏0
  • 2017-09-16 前端日報

    摘要:前端日報精選深入理解綁定請使用千位分隔符逗號表示網(wǎng)頁中的大數(shù)字跨頁面通信的各種姿勢你所不知道的濾鏡技巧與細(xì)節(jié)代碼質(zhì)量管控復(fù)雜度檢測中文翻譯基于與的三種代碼分割范式掘金系列如何構(gòu)建應(yīng)用程序冷星的前端雜貨鋪第期美團(tuán)旅行前端技術(shù)體系 2017-09-16 前端日報 精選 深入理解 js this 綁定請使用千位分隔符(逗號)表示web網(wǎng)頁中的大數(shù)字跨頁面通信的各種姿勢你所不知道的 CSS 濾...

    cheng10 評論0 收藏0
  • 淺談 Promise

    摘要:解決異步編程有兩種主要方式事件模型和回調(diào)函數(shù)。將異步操作以同步操作的流程表達(dá)出來,避免了層層嵌套回調(diào)函數(shù)。方法是的別名,相當(dāng)于函數(shù)的第一個參數(shù)傳入,第二個參數(shù)傳入發(fā)生錯誤時的回調(diào)函數(shù)。 JavaScript 解決異步編程有兩種主要方式:事件模型和回調(diào)函數(shù)。但是隨著業(yè)務(wù)越來越復(fù)雜,這兩種方式已經(jīng)不能滿足開發(fā)者的需求了,Promise 可以解決這方面的問題。為了更好的理解 Promise ...

    李濤 評論0 收藏0
  • [ JS 進(jìn)階 ] 異步編程 promise模式 的簡單實(shí)現(xiàn)

    摘要:為了降低異步編程的復(fù)雜性,所以。難理解請參考的誤區(qū)以及實(shí)踐異步編程的模式異步編程的種方法 異步編程 javascript異步編程, web2.0時代比較熱門的編程方式,我們平時碼的時候也或多或少用到,最典型的就是異步ajax,發(fā)送異步請求,綁定回調(diào)函數(shù),請求響應(yīng)之后調(diào)用指定的回調(diào)函數(shù),沒有阻塞其他代碼的執(zhí)行。還有像setTimeout方法同樣也是異步執(zhí)行回調(diào)的方法。 如果對異步編程...

    svtter 評論0 收藏0
  • JS 異步編程六種方案

    摘要:接下來介紹下異步編程六種方法。六生成器函數(shù)是提供的一種異步編程解決方案,語法行為與傳統(tǒng)函數(shù)完全不同,最大的特點(diǎn)就是可以控制函數(shù)的執(zhí)行。參考文章前端面試之道異步編程的種方法你不知道的中卷函數(shù)的含義和用法替代的個理由 前言 我們知道Javascript語言的執(zhí)行環(huán)境是單線程。也就是指一次只能完成一件任務(wù)。如果有多個任務(wù),就必須排隊(duì),前面一個任務(wù)完成,再執(zhí)行后面一個任務(wù)。 這種模式雖然實(shí)現(xiàn)起...

    longmon 評論0 收藏0

發(fā)表評論

0條評論

boredream

|高級講師

TA的文章

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