观察者讲解
目录
观察者定义
- 观察者模式定义了一种一对多的依赖关系,让多个观察者对象同时监听某一个目标对象,当这个目标对象的状态发生变化时,会通知所有观察者对象,使它们能够自动更新。
为什么要用观察者模式:
- 观察者模式的核心优势是观察者和被观察者充分解耦。这样发布者只需要负责触发事件即可,订阅者只需要专注处理逻辑即可,它们不需要彼此关心对方的存在和内在逻辑,使得应用的逻辑可以变得更加清晰,避免产生代码耦合问题。
有什么弊端:
- 观察者模式也是有坏处的,即它强行将代码间的关系进行分离,开发和维护的时候不容易一眼看到不同代码之间的逻辑关系。因此对于逻辑关联很强的代码,一般不建议使用观察者模式进行组织。
WebSocket:
- 本质上:基于Tcp 的全双工 协议,解决之前服务端推送问题(早期采取 Ajax轮询)经过 实例化后具备链接,发送请求的方法。
- 每一个 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
- 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)响应式原理:
function observe(target) {
if(target && typeof target === 'object') {
Object.keys(target).forEach((key)=> {
defineReactive(target, key, target[key])
})
}
}
data(){
a:{
b:{
1
}
}

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