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

資訊專欄INFORMATION COLUMN

Make a simple custom EventEmitter

fizz / 2629人閱讀

Thoughts

Recently I have been reading the book Async Javascript about JS asynchronicity and JS event is one of the useful solutions to the problem. To get a deeper understanding of how events work, I create a custom EventEmitter which constains most of the working functionalities of Node EventEmitter. The source code is no more than 60 lines.

General ideas

The general ideas is to have an object (this.handlers) to hold the mapping from event name(type: string) to its associated listeners/handlers(type: Array). When each event is triggerd, walk through the associated listeners/handlers and execute them.

class Emitter {
    constructor(){
        /**
         * keep mapping information。
         * e.g. 
         *   {
         *      "event1": [fn1, fn2],
         *      "event2": [fn3, fn4, fn5]
         *   }
         */
        this.handlers = {};
    }
}
Some details about the methods on - event binding
on(evt, handler) {
    this.handlers[evt] = this.handlers[evt] || [];
    let hdl = this.handlers[evt];
    hdl.push(handler);
    return this;
}

We don"t check the duplicates when binding the handler for simplicity. That is to say, if you call on for the same function twice, then it will be called twice when the event is triggered. The method returns this to allow for method chaining。

off - event unbinding
removeListener(evt, handler) {
    this.handlers[evt] = this.handlers[evt] || [];
    let hdl = this.handlers[evt];
    let index = hdl.indexOf(handler);
    if(index >= 0) {
        hdl.splice(index, 1);
    }
    return this;
}

Note that here we compare the function reference with strict comparision when unbinding a function. Function in Javascript is compared by their reference, same as how objects comparision works.

function f1() {
    console.log("hi");
}

function f2() {
    console.log("hi");
}

let f3 = f1;
console.log(f1 === f2); //false
console.log(f1 === f3); //true
once - binding, but only can be triggerd once
once(evt, handler) {
    this.handlers[evt] = this.handlers[evt] || [];
    let hdl = this.handlers[evt];
    hdl.push(function f(...args){
        handler.apply(this, args);
        this.removeListener(evt, f);
    });
    return this;
}

It works similarly with on method. But we need to wrap the handler with another function such that we can remove the binding once the handler is executed to achieve triggered only once.

emit - trigger event
emit(evt, ...args) {
    this.handlers[evt] = this.handlers[evt] || [];
    let hdl = this.handlers[evt];
    hdl.forEach((it) => {
        it.apply(this, args);
    });
    return this;
}

When an event is triggered, find all its associated handlers(i.e. this.handlers[evt]) and execute them.

eventNames - get the list of registered events which has active(i.e. not-empty) handlers
eventNames() {
    return Object.keys(this.handlers).reduce((arr, evt) => {
        if(this.listenerCount(evt)) {
            arr.push(evt);
        }
        return arr;
    }, []);
}

Here we don"t simply return all the keys of the this.handlers , as some events can be binded with some handlers and then remove them afterwards. In the case, the event name exists as a valid key in this.handlers but without active handlers. E.g.

let server = new Emitter();
let fn = function(){};
server.on("connection", fn);
server.removeListener("connection", fn);
server.handlers.connection; //[]

Therefore, we need to filter out the events with empty hanlders. Here we use Array.prototype.reduce to make the code a little bit cleaner. There are many situations where reduce can be useful, such as computing the sum of an array:

function sumWithForEach(arr) { // with forEach
    let sum = 0;
    arr.forEach(it => {
        sum += it;
    })
    return sum;
}

function sumWithReduce(arr) { // with reduce
    return arr.reduce((sum, current) => {
        return sum + current;
    })
}
Reference

Async Javascript

Notice

If you benefit from this Repo,Please「Star 」to Support.

If you want to follow the latest news/articles for the series of reading notes, Please 「Watch」to Subscribe.

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

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

相關(guān)文章

  • node.js入門學(xué)習(xí)筆記整理——基礎(chǔ)篇

    摘要:的介紹一般是這樣在中,類是隨內(nèi)核一起發(fā)布的核心庫。庫為帶來了一種存儲原始數(shù)據(jù)的方法,可以讓處理二進制數(shù)據(jù),每當需要在中處理操作中移動的數(shù)據(jù)時,就有可能使用庫。這樣傳遞數(shù)據(jù)會更快。 零、開始之前 1、 首先解釋一下node.js是什么? 2、node.js和javascript有什么不同? 1)因為javascript主要是用在browser,而node.js是在server或者你的電腦...

    Tamic 評論0 收藏0
  • MSCI 720

    MSCI 720 Monday Jan 9 Lec 3/36 Syllabus TREC Agreement Summary-Review Architecture TREC text format Tokenization Tutorials will be used to tutor and help students to complete the assignments Outcome...

    DevTalking 評論0 收藏0
  • angularV4+學(xué)習(xí)筆記

    摘要:注解的元數(shù)據(jù)選擇器頁面渲染時,組件匹配的選擇器使用方式采用標簽的方式。當然必要的,在需要用到的的模塊中引入引入的指令,放在聲明里面引入的模塊引導(dǎo)應(yīng)用的根組件關(guān)于的元數(shù)據(jù)還未完全,所以后面會繼續(xù)完善。 angular學(xué)習(xí)筆記之組件篇 showImg(https://i.imgur.com/NQG0KG1.png); 1注解 1.1組件注解 @Component注解,對組件進行配置。 1....

    galaxy_robot 評論0 收藏0
  • angularV4+學(xué)習(xí)筆記

    摘要:注解的元數(shù)據(jù)選擇器頁面渲染時,組件匹配的選擇器使用方式采用標簽的方式。當然必要的,在需要用到的的模塊中引入引入的指令,放在聲明里面引入的模塊引導(dǎo)應(yīng)用的根組件關(guān)于的元數(shù)據(jù)還未完全,所以后面會繼續(xù)完善。 angular學(xué)習(xí)筆記之組件篇 showImg(https://i.imgur.com/NQG0KG1.png); 1注解 1.1組件注解 @Component注解,對組件進行配置。 1....

    LoftySoul 評論0 收藏0

發(fā)表評論

0條評論

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