美文网首页
js观察者模式学习总结:

js观察者模式学习总结:

作者: 欧阳司空 | 来源:发表于2017-07-23 11:48 被阅读193次

    观察者模式:

    这是一种创建松散耦合代码的技术。它定义对象间 一种一对多的依赖关系,当一个对象的状态发生改变时,所有依赖于它的对象都将得到通知。由主体和观察者组成,主体负责发布事件,同时观察者通过订阅这些事件来观察该主体。主体并不知道观察者的任何事情,观察者知道主体并能注册事件的回调函数。

    node事件
    <code>
    server.on('connection', (stream) => {
    console.log('someone connected!');
    });
    server.removeListener('connection', callback);
    server.emit('connection', callback);
    </code>
    <p>
    node 在一个事件里面只能注册10个事件
    </p>

    实现它的功能

    注册与发布
    <code>
    function Events(name) {
    this.name = name;
    this._events = {};
    }
    Events.prototype.on = function(eventname, callback) {
    if(this._events[eventname]) {
    this._events[eventname].push(callback)
    }else{
    this._events[eventname]=[callback]
    }
    }
    Events.prototype.emit=function(eventname){
    var callbacks=this._events[eventname]
    callbacks.forEach(function(callback){
    callback()
    })
    }
    var girl = new Events()
    girl.on('长发及腰',function(){
    console.log('长发及腰')
    })
    girl.on('长发及腰',function(){
    console.log('长发及腰2')
    })
    girl.emit('长发及腰')
    </code>

    传说是阿里面试题 实现效果

    <code>
    const emitter = new EventEmitter()
    const sayHi = (name) => console.log(Hello ${name})
    const sayHi2 = (name) => console.log(Good night, ${name})
    emitter.on('hi', sayHi)
    emitter.on('hi', sayHi2)
    emitter.emit('hi', 'ScriptOJ')
    // => Hello ScriptOJ
    // => Good night, ScriptOJ
    emitter.off('hi', sayHi)
    emitter.emit('hi', 'ScriptOJ')
    // => Good night, ScriptOJ
    const emitter2 = new EventEmitter()
    emitter2.on('hi', (name, age) => {
    console.log(I am ${name}, and I am ${age} years old)
    })
    emitter2.emit('hi', 'Jerry', 12)
    // => I am Jerry, and I am 12 years old
    </code>

    实现它的功能

    注册与发布
    <code>
    function EventEmitter(name) {
    this.name = name;
    this._events = {};
    }
    EventEmitter.prototype.on = function(eventname, callback) {
    if(this._events[eventname]) {
    this._events[eventname].push(callback)
    } else {
    this._events[eventname] = [callback]
    }
    }
    EventEmitter.prototype.emit = function(eventname) {
    var args = Array.prototype.slice.call(arguments, 1)
    var callbacks = this._events[eventname]
    var self = this
    callbacks.forEach(function(callback) {
    callback.apply(self, args)
    })
    }
    EventEmitter.prototype.off = function(eventname, callback) {
    var callbacks = this._events[eventname]
    let cbindex = callbacks.indexOf(callback)
    if(cbindex === -1) {
    console.log('没有该方法')
    } else {
    callbacks.splice(cbindex, 1);
    }
    }
    const emitter = new EventEmitter()
    const sayHi = (name) => console.log(Hello ${name})
    const sayHi2 = (name) => console.log(Good night, ${name})

    emitter.on('hi', sayHi)
    emitter.on('hi', sayHi2)
    emitter.emit('hi', 'ScriptOJ')
    Hello ScriptOJ
    Good night, ScriptOJ

    emitter.off('hi', sayHi)
    emitter.off('hi', sayHi3)
    emitter.emit('hi', 'ScriptOJ')
    Good night, ScriptOJ

    const emitter2 = new EventEmitter()
    emitter2.on('hi', (name, age) => {
    console.log(I am ${name}, and I am ${age} years old)
    })
    emitter2.emit('hi', 'Jerry', 12)
    </code>

    ES6 class方法
    <code>
    class EventEmitter {
    constructor(name) {
    this.name = name;
    this._events = {};
    }
    on(eventname, callback) {
    if(this._events[eventname]) {
    this._events[eventname].push(callback)
    } else {
    this._events[eventname] = [callback]
    }
    }
    emit(eventname, ...args) {
    let callbacks = this._events[eventname]
    callbacks.forEach(function(callback) {
    callback(args)
    })
    }
    off(eventname,cb){
    let callbacks = this._events[eventname];
    let cbindex=callbacks.indexOf(cb)
    if(cbindex===-1){
    console.log('该方法不存在')
    }else{
    callbacks.splice(cbindex,1)
    }
    }
    }
    const emitter = new EventEmitter()
    const sayHi = (name) => console.log(Hello ${name})
    const sayHi2 = (name) => console.log(Good night, ${name})
    emitter.on('hi', sayHi)
    emitter.on('hi', sayHi2)
    emitter.emit('hi', 'ScriptOJ')
    emitter.off('hi', sayHi)
    emitter.off('hi', 'sayHi3')
    emitter.emit('hi', 'ScriptOJ')
    const emitter2 = new EventEmitter()
    emitter2.on('hi', (name, age) => {
    console.log(I am ${name}, and I am ${age} years old)
    })
    emitter2.emit('hi', 'Jerry', 12)</code>

    redux 使用观察模式代码

    <code>
    let currentListeners = []
    let nextListeners = currentListeners
    function ensureCanMutateNextListeners() {
    if (nextListeners === currentListeners) {
    nextListeners = currentListeners.slice()
    }
    }
    function subscribe(listener) {
    if (typeof listener !== 'function') {
    throw new Error('Expected listener to be a function.')
    }
    //判断是否是函数
    let isSubscribed = true
    ensureCanMutateNextListeners()
    nextListeners.push(listener)
    return function unsubscribe() {
    if (!isSubscribed) {
    return
    }
    isSubscribed = false
    ensureCanMutateNextListeners()
    const index = nextListeners.indexOf(listener)
    nextListeners.splice(index, 1)
    }
    }

    每一次执行dispath 都会执行监听函数
    function dispatch(action) {
    if (!isPlainObject(action)) {
    throw new Error(
    'Actions must be plain objects. ' +
    'Use custom middleware for async actions.'
    )
    }
    if (typeof action.type === 'undefined') {
    throw new Error(
    'Actions may not have an undefined "type" property. ' +
    'Have you misspelled a constant?'
    )
    }
    if (isDispatching) {
    throw new Error('Reducers may not dispatch actions.')
    }
    try {
    isDispatching = true
    currentState = currentReducer(currentState, action)
    } finally {
    isDispatching = false
    }
    const listeners = currentListeners = nextListeners
    for (let i = 0; i < listeners.length; i++) {
    const listener = listeners[i]
    listener()
    }
    return action
    }
    </code>

    总结,写东西真累,以后会习惯的。。。

    相关文章

      网友评论

          本文标题:js观察者模式学习总结:

          本文链接:https://www.haomeiwen.com/subject/ddwpkxtx.html