首頁  >  文章  >  web前端  >  JS事件先發布後訂閱的方法

JS事件先發布後訂閱的方法

php中世界最好的语言
php中世界最好的语言原創
2018-03-16 11:20:032167瀏覽

這次帶給大家JS事件先發布後訂閱的方法,實現JS事件先發布後訂閱的注意事項有哪些,下面就是實戰案例,一起來看一下。

之前寫過一個的事件管理器,就是普通的先訂閱後發布模式。但實際場景中我們需要做到後訂閱的也能收到發布的消息。例如我們關注微信公眾號,還是能看到歷史消息的。類似qq離線訊息,我先發給你,你登入了就能收到了。 就是確保訂閱該事件的方法都能被執行

 var eventManger = {
        cached: {},
        handlers: {},        //类型,绑定事件 
        addHandler: function (type, handler) {            if (typeof handler !== "function") return;            if (typeof this.handlers[type] == "undefined") {                this.handlers[type] = [];
            }            this.handlers[type].push(handler);            if (this.cached[type] instanceof Array) {                //说明有缓存的 可以执行
                handler.apply(null, this.cached[type]);
            }
        },
        removeHandler: function (type, handler) {            var events = this.handlers[type];            for (var i = 0, len = events.length; i < len; i++) {                if (events[i] == handler) {
                    events.splice(i, 1);                    break;
                }
            }
        },
        trigger: function (type) {            //如果有订阅的事件,这个时候就触发了
            if (this.handlers[type] instanceof Array) {                var handlers = this.handlers[type];                var args = Array.prototype.slice.call(arguments, 1);                for (var i = 0, len = handlers.length; i < len; i++) {
                    handlers[i].apply(null, args);
                }
            }            //默认缓存
            this.cached[type] = Array.prototype.slice.call(arguments, 1);
        }
    };

其實就是增加了幾行程式碼。快取下最後一次觸發的時的參數。 然後在addhandle的時候進行判斷,如果訂閱的時候已經有快取的參數了,表示該方法可以執行了。

eventManger.addHandler("test", function (res) {
    console.log("先订阅,后发布1", res);
})
eventManger.trigger("test", 2);
eventManger.addHandler("test", function (res) {
    console.log("先发布,后订阅2", res);
})
eventManger.addHandler("test", function (res) {
    console.log("先发布,后订阅3", res);
})

我實際的場景是這樣的A事件觸發之後,才能執行B方法。但B方法需要在C方法完成之後。也就是B依賴A和C的完成。且A幾乎每次都會很快觸發,當然可以設兩個個開關變數和一個代理函數,等兩個事件都完成之後再do B。程式碼如下:

var aReady = false;var cReady = false;
eventManger.addHandler("A", function () {
    aReady = true;
    console.log("do A");
    proxyC();
});
eventManger.trigger("A", 2);function doB() {
    console.log("do B");    //实际B中的方法需要在A事件成功之后才能执行}function doC() {
    console.log("do C");
    cReady = true;
    proxyC();
}function proxyC() {
    aReady && cReady && doB();
}
doC();

這樣功能是實現了,但是可讀性差了,而且事件訂閱必須要對位置,如果在trigger之前,doB就永遠執行不了,而且程式碼上多了兩個變數和一個方法,最愚蠢的是用一個變數加setTimeout去判斷狀態,這就可能會陷入死循環

var aReady = false;
eventManger.addHandler("A", function () {
    aReady = true;
    console.log("do A");
});function doB() {
    console.log("do B");    //实际B中的方法需要在A事件成功之后才能执行}function doC() {
    console.log("do C");    if (!aReady) {
        console.log("wating...");        setTimeout(doC, 50);        return;
    }
    doB();
}
doC();
eventManger.trigger("A", 2);//模拟A事件触发迟

這種辦法最不可取吧。因為外部事件可能掛掉,這兒就走不出去了。等於是挖了一個坑。但如果事件支援先發布,後訂閱,問題就簡單了:

eventManger.trigger("A", 2);function doB() {
    console.log("do B");    //实际B中的方法需要在A事件成功之后才能执行}function doC() {
    console.log("do c");
    eventManger.addHandler("A", function () {
        console.log("do a");
        doB();
    });
}
doC();

 

#這樣就清晰了很多。事件訂閱也不必那麼在意呼叫的位置了。以上只是記住最近的一次的呼叫參數,可以用於後訂閱的事件觸發。這適合一次性事件(一個週期只會觸發一次的事件)。如果是像是推播訊息的事件,會不斷的觸發,如果想要確保也能獲得全部的歷史記錄,就需要記住所有的參數。這是一種情況;實際上可能會有更多的流程依賴,當然對於流程控制有很多辦法,也有很多函式庫支援。例如promise和async。本文只是闡述了一個事件和方法的流程相關場景,也許對你有啟發。

相信看了本文案例你已經掌握了方法,更多精彩請關注php中文網其它相關文章!

推薦閱讀:

vue的自訂動態元件使用詳解

#protobuf.js 與Long.js的使用詳解

以上是JS事件先發布後訂閱的方法的詳細內容。更多資訊請關注PHP中文網其他相關文章!

陳述:
本文內容由網友自願投稿,版權歸原作者所有。本站不承擔相應的法律責任。如發現涉嫌抄襲或侵權的內容,請聯絡admin@php.cn