zoukankan      html  css  js  c++  java
  • js观察者模式发布/订阅

    实习期结束,最近回到学校开始学习node.js,node果然是强大。不过在涉及到文件操作的时候,发现要大量使用异步回掉操作。

    以前在写页面的时候,从没这么多异步操作,只有在使用'setInterval'和'XMLHttpRequest'时了解了一下异步编程。这次在学习node的过程中,把异步回掉算是弄清楚了。但是在编码书写代码的时候,陷入了回调金字塔(callback hell)。使用es6Promise解决了一些问题。也看到了EventProxy模块基于事件驱动的解决方案。

    在使用EventProxy的过程中,有种似曾相识的感觉。有点像观察者模式发布/订阅。首先使用数组缓存订阅者订阅的消息,当订阅者订阅消息的时候,把订阅的消息push到指定消息的队列中,当发布者发布消息的时候,我们遍历执行push到指定消息队列中的回调事件。

    而订阅者不需要关心发布者什么时候发布消息。
    而发布者不需要关心订阅者订阅的状态。

    var observer = new Observe();
    var callback = function(num) {
        console.log("event:"+num); // 输出event:2
    };
    // 订阅消息
    observer.listen("event1", callback);
    observer.listen("event2", callback);
    // 移除订阅消息1
    observer.remove('event1', callback);
    // 发布者发布消息
    observer.trigger("event1",1);
    observer.trigger("event2",2);
    

    具体代码如下:

    function Observe() {
        // 缓存订阅者的消息队列
        this._list = [];
    }
    /**
     *
     * 订阅者订阅消息
     * @param  {string}   key 消息名
     * @param  {Function} fn  回调事件
     * @return {Null}       
     */
    Observe.prototype.listen = function(key, fn) {
        if (!this._list[key]) {
            this._list[key] = [];
        }
        // 订阅消息,添加到缓存列表中
        this._list[key].push(fn);
    };
    /**
     * 
     * 移除订阅的消息
     * @param  {string}   key 消息名
     * @param  {Function} fn  回掉事件
     * @return {Null}       
     */
    Observe.prototype.remove = function(key, fn) {
        // 获取当前key下的消息记录
        var arrFn = this._list[key];
        if (!arrFn) return false;
        // 未指定fn则删除当前key下所有的订阅消息
        if (!fn) {
            arrFn.length = 0;
        } else {
            for (var i = 0; i < arrFn.length; i++) {
                if (fn === arrFn[i]) {
                    arrFn.splice(i,1);
                }
            }
        }
    };
    /**
     * 发布者发布消息
     * @param  {string} key 消息名
     * @param  {string | Object} 消息数据
     * @return {Null}  
     */
    Observe.prototype.trigger = function() {
        // 得到key,第二个及以上的参数
        var key = Array.prototype.shift.call(arguments);
        var args = arguments;
        var arrFn = this._list[key];
        if (!arrFn || arrFn.length === 0) {
            return;
        }
        // 遍历执行当前key下面的所有消息
        for (var i = 0; i < arrFn.length; i++) {
            arrFn[i].apply(this, args);
        }
    };
  • 相关阅读:
    Educational Codeforces Round 83 --- F. AND Segments
    Educational Codeforces Round 83 --- G. Autocompletion
    SEERC 2019 A.Max or Min
    2019-2020 ICPC Southwestern European Regional Programming Contest(Gym 102501)
    Educational Codeforces Round 78 --- F. Cards
    今天我学习了一门全新的语言
    codeforces 1323D 题解(数学)
    Educational Codeforces Round 80 (Div. 2) 题解 1288A 1288B 1288C 1288D 1288E
    Educational Codeforces Round 81 (Div. 2) 题解 1295A 1295B 1295C 1295D 1295E 1295F
    Codeforces Round #617 (Div. 3) 题解 1296C 1296D 1296E 1296F
  • 原文地址:https://www.cnblogs.com/Aralic/p/4799372.html
Copyright © 2011-2022 走看看