请使用原生代码实现一个Events模块,可以实现自定义事件的订阅,触发,移除功能

216 阅读1分钟

题目

//请使用原生代码实现一个Events模块,可以实现自定义事件的订阅,触发,移除功能
const fn1 = (...args)=>console.log('I want sleep1', ...args)
const fn2 = (...args)=>console.log('I want sleep2', ...args)

const event = new Events();
event.on('sleep', fn1, 1, 2, 3);
event.on('sleep', fn2, 1, 2, 3);
event.fire('sleep', 4, 5, 6);
// I want sleep1 1 2 3 4 5 6
// I want sleep2 1 2 3 4 5 6
event.off('sleep', fn1);
event.once('sleep', ()=>console.log('I want sleep once'));
event.fire('sleep');

实现

class Events {
    map = new Map();
    onceMap = new Map();
    constructor() {}
    curry(fn, ...args) {
        const m = (...args2)=>{
            fn(...args, ...args2)
        }
        ;
        m.fn = fn;
        return m;
    }
    on(name, fn, ...args) {
        const {map, curry} = this;
        let arr = map.get(name);
        arr ? arr.push(curry(fn, ...args)) : arr = [curry(fn, ...args)]
        map.set(name, arr)
    }
    fire(name, ...args2) {
        const {map, onceMap} = this;
        const arr = map.get(name);
        arr && arr.forEach(fn=>fn(...args2))

        const onceFn = onceMap.get(name)
        if (onceFn) {
            onceFn();
            onceMap.delete(name)
        }
    }
    off(name, fn) {
        const {map} = this;
        const arr = map.get(name)
        const index = arr.findIndex(i=>i.fn === fn);
        index !== -1 && arr.splice(index, 1)
    }
    once(name, fn) {
        const {onceMap} = this;
        onceMap.set(name, fn);
    }
}

//请使用原生代码实现一个Events模块,可以实现自定义事件的订阅,触发,移除功能
const fn1 = (...args)=>console.log('I want sleep1', ...args)
const fn2 = (...args)=>console.log('I want sleep2', ...args)

const event = new Events();
event.on('sleep', fn1, 1, 2, 3);
event.on('sleep', fn2, 1, 2, 3);
event.fire('sleep', 4, 5, 6);
// I want sleep1 1 2 3 4 5 6
// I want sleep2 1 2 3 4 5 6
event.off('sleep', fn1);
event.once('sleep', ()=>console.log('I want sleep once'));
event.fire('sleep');