vaakian / vaakian.github.io

some notes
https://vaakian.github.io
3 stars 0 forks source link

实现观察者模式的一种 #13

Open vaakian opened 3 years ago

vaakian commented 3 years ago

发布订阅

on添加行为订阅,emit触发该行为。

function EventEmitter() {
    let handlers = {

    };
    return {
        on(action, handler) {
            if(handlers[action] === undefined) {
                handlers[action] = [];
            }
            handlers[action].push(handler);
        },
        emit(action, params) {
            let action_handlers = handlers[action];
            if(action_handlers !== undefined) {
                for(handler of action_handlers) {
                    handler(params);
                }
            }
        }
    }
}

xwj = new EventEmitter();
xwj.on('HOME_WORK_DONE', (params) => {
    console.log("Hello, I'm XWJ, My home work should be done as you see this message.");
    console.log(params);
});
vaakian commented 2 years ago

es6版本,通用参数长度。 且回掉应该异步类型。

class EventEmitter {
    callbackMap = new Map();
    on(event, fn) {
        this.putCallbacks(event, fn);
    }
    emit(event, ...args) {
        const callbacks = this.getCallbacks(event);
        callbacks.forEach(fn => {
            // emit不要阻塞后续运行
            fn instanceof Function && queueMicrotask(() => fn(...args));
        })
    }
    off(event, fn) {
        const callbacks = this.getCallbacks(event);
        for (let i = 0; i < callbacks.length; i++) {
            // 函数引用相同
            if (fn === callbacks[i]) {
                callbacks.splice(i, 1);
                break;
            }
        }
    }
    getCallbacks(event) {
        const callbacks = this.callbackMap[event];
        return Array.isArray(callbacks) ? callbacks : [];
    }
    putCallbacks(event, fn) {
        const callbacks = this.callbackMap[event];
        if (Array.isArray(callbacks)) {
            callbacks.push(fn);
        } else {
            this.callbackMap[event] = [fn];
        }
    }
}

let ob = new EventEmitter();
const sum = (a, b) => {
    console.log(a + b);
};
ob.on('sum', sum);
ob.on('multiply', (a, b) => {
    console.log(a * b)
})
ob.emit('sum', 5, 6);
ob.emit('multiply', 7, 3)
vaakian commented 2 years ago

观察者模式


/* 
观察者:`update`
被观察者:`add`,`remove`,`notify`
/*

function Observer(name) {
    this.name = name;
}

Observer.prototype.update = function (...args) {
    console.log(`${this.name} updated`, args)
}
Observer.prototype.observe = function (observableObject) {
    observableObject.add && observableObject.add(this)
}
function Observable() {
    this.observers = [];
}

Observable.prototype.add = function (observer) {
    this.observers.push(observer)
}

Observable.prototype.notify = function (...args) {
    for (let observer of this.observers) {
        observer.update(...args)
    }
}

Observable.prototype.remove = function (observer) {
    for (let i = 0; i < this.observers.length; ++i) {
        if (this.observers[i] === observer) this.splice(i, 1)
    }
}

let obj = new Observable()

let [lucy, marry] = [new Observer('lucy'), new Observer('marry')]

lucy.observe(obj)
marry.observe(obj)

setTimeout(() => {
    obj.notify(1, 2, 3)
}, 200)
``