观察者模式分享-老生新谈

75 阅读5分钟

观察者讲解

目录

观察者定义

  1. 观察者模式定义了一种一对多的依赖关系,让多个观察者对象同时监听某一个目标对象,当这个目标对象的状态发生变化时,会通知所有观察者对象,使它们能够自动更新。

为什么要用观察者模式:

  1. 观察者模式的核心优势是观察者和被观察者充分解耦。这样发布者只需要负责触发事件即可,订阅者只需要专注处理逻辑即可,它们不需要彼此关心对方的存在和内在逻辑,使得应用的逻辑可以变得更加清晰,避免产生代码耦合问题。

有什么弊端:

  1. 观察者模式也是有坏处的,即它强行将代码间的关系进行分离,开发和维护的时候不容易一眼看到不同代码之间的逻辑关系。因此对于逻辑关联很强的代码,一般不建议使用观察者模式进行组织。

WebSocket:

  1. 本质上:基于Tcp 的全双工 协议,解决之前服务端推送问题(早期采取 Ajax轮询)经过 实例化后具备链接,发送请求的方法。
  2. 每一个 WebSocket 实例都是一个观察者,socket服务充当被观察者;

Promise 观察者模式&发布订阅模式

const pending = 'pending'
const resolved = 'resolved'
const rejected = 'rejected'
const resolvepromise = (promise2, x, resolve, reject) => {
  if (promise2 === x) {
    return reject(new TypeError('不能返回自身'))
  }
  if (typeof x === 'object' && typeof x !== null || typeof x === 'function') {
    //由于测试的时候即调用成功,也调用失败resolve(),reject()
    try {
      let then = x.then
      if (typeof then === 'function') {//是一个promise
        then.call(x, y => {
          resolvepromise(promise2, y, resolve, reject)//什么意思就是说这个,resolve可能继续返回一个promise,所以想递归不断得到一个普通值后再去返回

        }, r => {
          reject(r)
        })

      } else {
        resolve(x)//这里就是说这个x亦可能是普通值then里面返回一个普通值自然,调用promise2的一个resolve(x)
      }

    } catch (error) {
      reject(error)
    }

  }

}
class Promise {
    constructor(executor) {
        this.status = pending
        this.value = undefined
        this.reason = undefined
        this.onfullfiledCallbacks = []
        this.onrejectedCallbacks = []
        let resolve = (value) => {
            if (this.status === pending) {
                this.value = value
                this.status = resolved
    //订阅,开始执行之前暂存的成功的回调,或者失败的回调
                this.onfullfiledCallbacks.forEach(fn => fn())
            }
        }
        let reject = (reason) => {
            if (this.status === pending) {
                this.status = rejected
                this.reason = reason
                this.onrejectedCallbacks.forEach(fn => fn())
            }//用箭头函数是因为要来去继承外部代码快的this

        }
        try {
            executor(resolve, reject)
        } catch (error) {
            reject(error)
        }
    }

    then(onfullfiled, onrejected) {
        let promsie2 = new Promise((resolve, reject) => {
            //同步的情况
      // 当判断状态发生变更的时候,去通知执行对应成功的回调,或是失败的回调
            if (this.status === resolved) {
                setTimeout(() => {
                    try {
                        let x = onfullfiled(this.value)//这个是then()方法返return 的一个结果
                        ResolvePromise(x, promsie2, resolve, reject)
                    } catch (error) {
                        reject(error)
                    }
                })

                if (this.status === rejected) {
                    setTimeout(() => {
                        try {
                            let x = onrejected(this.reason)//这个是then()方法返return 的一个结果
                            ResolvePromise(x, promsie2, resolve, reject)
                        } catch (error) {
                            reject(error)
                        }
                    })
                }
                //异步的情况,当立即执行函数内部存在异步,先进行发布
                if (this.status === pending) {
                    this.onfullfiledCallbacks.push(() => {
                        setTimeout(() => {
                            try {
                                let x = onfullfiled(this.value)//这个是then()方法返return 的一个结果
                                ResolvePromise(x, promsie2, resolve, reject)
                            } catch (error) {
                                reject(error)
                            }
                        })

                    })
                    this.onrejectedCallbacks.push(() => {
                        setTimeout(() => {
                            try {
                                let x = onrejected(this.reason)//这个是then()方法返return 的一个结果
                                ResolvePromise(x, promsie2, resolve, reject)
                            } catch (error) {
                                reject(error)
                            }
                        })

                    })

                }

            }

        })
        return promsie2

    }
}

module.exports = Promise
  1. promise 的发布订阅体现在哪里。
    //这里会存在一个问题就是当立即执行函数内部是异步的,当执行到微任务时先将立即执行函数push到成功或失败的数组(发布)
    const result = new Promise((resolve, reject) => {
      setTimeout(() => {
        // reject(222)
        resolve(222)
    
      }, 400);
    
    }).then((value) =>
      console.log('value', value), (reason) => reason)
    console.log('result', result)
    

Mitt 库:

export type EventType = string | symbol;

// An event handler can take an optional event argument
// and should not return a value
export type Handler<T = unknown> = (event: T) => void;
export type WildcardHandler<T = Record<string, unknown>> = (
  type: keyof T,
  event: T[keyof T]
) => void;

// An array of all currently registered event handlers for a type
export type EventHandlerList<T = unknown> = Array<Handler<T>>;
export type WildCardEventHandlerList<T = Record<string, unknown>> = Array<WildcardHandler<T>>;

// A map of event types and their corresponding event handlers.
export type EventHandlerMap<Events extends Record<EventType, unknown>> = Map<
  keyof Events | '*',
  EventHandlerList<Events[keyof Events]> | WildCardEventHandlerList<Events>
>;

export interface Emitter<Events extends Record<EventType, unknown>> {
  all: EventHandlerMap<Events>;

  on<Key extends keyof Events>(type: Key, handler: Handler<Events[Key]>): void;
  on(type: '*', handler: WildcardHandler<Events>): void;

  off<Key extends keyof Events>(type: Key, handler?: Handler<Events[Key]>): void;
  off(type: '*', handler: WildcardHandler<Events>): void;

  emit<Key extends keyof Events>(type: Key, event: Events[Key]): void;
  emit<Key extends keyof Events>(type: undefined extends Events[Key] ? Key : never): void;
}

/**
 * Mitt: Tiny (~200b) functional event emitter / pubsub.
 * @name mitt
 * @returns {Mitt}
 */
export default function mitt<Events extends Record<EventType, unknown>>(
  all?: EventHandlerMap<Events>
): Emitter<Events> {
  type GenericEventHandler =
    | Handler<Events[keyof Events]>
    | WildcardHandler<Events>;
  all = all || new Map();

  return {

    /**
     * A Map of event names to registered handler functions.
     */
    all,

    /**
     * Register an event handler for the given type.
     * @param {string|symbol} type Type of event to listen for, or `'*'` for all events
     * @param {Function} handler Function to call in response to given event
     * @memberOf mitt
     */
    on<Key extends keyof Events>(type: Key, handler: GenericEventHandler) {
      const handlers: Array<GenericEventHandler> | undefined = all!.get(type);
      if (handlers) {
        handlers.push(handler);
      }
      else {
        all!.set(type, [handler] as EventHandlerList<Events[keyof Events]>);
      }
    },

    /**
     * Remove an event handler for the given type.
     * If `handler` is omitted, all handlers of the given type are removed.
     * @param {string|symbol} type Type of event to unregister `handler` from (`'*'` to remove a wildcard handler)
     * @param {Function} [handler] Handler function to remove
     * @memberOf mitt
     */
    off<Key extends keyof Events>(type: Key, handler?: GenericEventHandler) {
      const handlers: Array<GenericEventHandler> | undefined = all!.get(type);
      if (handlers) {
        if (handler) {
          handlers.splice(handlers.indexOf(handler) >>> 0, 1);
        }
        else {
          all!.set(type, []);
        }
      }
    },

    /**
     * Invoke all handlers for the given type.
     * If present, `'*'` handlers are invoked after type-matched handlers.
     *
     * Note: Manually firing '*' handlers is not supported.
     *
     * @param {string|symbol} type The event type to invoke
     * @param {Any} [evt] Any value (object is recommended and powerful), passed to each handler
     * @memberOf mitt
     */
    emit<Key extends keyof Events>(type: Key, evt?: Events[Key]) {
      let handlers = all!.get(type);
      if (handlers) {
        (handlers as EventHandlerList<Events[keyof Events]>)
          .slice()
          .map((handler) => {
            handler(evt!);
          });
      }

      handlers = all!.get('*');
      if (handlers) {
        (handlers as WildCardEventHandlerList<Events>)
          .slice()
          .map((handler) => {
            handler(type, evt!);
          });
      }
    }
  };
}




Vue(2)响应式原理:

image_OFMjmLIwU3.png

function observe(target) {
    if(target && typeof target === 'object') {
        Object.keys(target).forEach((key)=> {
            defineReactive(target, key, target[key])
        })
    }
}
data(){
a:{
b:{
1
}
}

![image_OFMjmLIwU3.png](https://p3-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/80a8a1d3852444619037c14c42eca813~tplv-k3u1fbpfcp-jj-mark:0:0:0:0:q75.image#?w=1200&h=750&s=268777&e=png&b=ffffff)
}

function defineReactive(target, key, val) {
    // 属性值也可能是object类型,这种情况下需要调用observe进行递归遍历
    observe(val)
    Object.defineProperty(target, key, {
        enumerable: true,
        configurable: false, 
        get: function () {
            return val;
        },
        set: function (value) {
            console.log(`${target}属性的${key}属性从${val}值变成了了${value}`)
            val = value
        }
    });
}

下面实现订阅者 Dep建立数据与watcher 的桥梁

// 定义订阅者类Dep
class Dep {
    constructor() {
        // 初始化订阅队列
        this.subs = []
    }
  
    addSub(sub) {
        this.subs.push(sub)
    }
  
    notify() {
        this.subs.forEach((sub)=>{
            sub.update()
        })
    }
}

现在我们可以改写 defineReactive 中的 setter 方法,在监听器里去通知订阅者了:

function defineReactive(target, key, val) {
    const dep = new Dep()
    // 监听当前属性
    observe(val)
    Object.defineProperty(target, key, {
        set: (value) => {
            // 通知所有订阅者
            dep.notify()
        }
    })
}

babel

  1. V8引擎在执行js代码的时候,会经历一个parse transform generator .
  • parse:通过 parser 把源码转成抽象语法树(AST)
  • transform:遍历 AST,调用各种 transform 插件对 AST 进行增删改
  • generate:把转换后的 AST 打印成目标代码,并生成 sourcemap.
  • 也就是说当babel插件观测到当前的generate 阶段后,就会执行对应的 visitor函数里面的逻辑。