daily-share
daily-share copied to clipboard
简单的了解发布与订阅模式(2020-1-19)
简单的了解发布与订阅模式(2020-1-19)
简单的了解发布订阅模式,简单来说,发布订阅模式也是观察者模式。
var salesOffices = {}
salesOffices.clientLis = [] // 存放订阅的函数
salesOffices.listen = function(fn) { // 添加订阅者
this.clientLis.push(fn)
}
salesOffices.trigger = function() { // 发布消息
for(var i =0, fn; fn = this.clientLis[i++]; ) {
fn.apply(this, arguments)
}
}
简单的模式
简单的发布订阅模式
// 实现简单的订阅模式
var salesOffice = {} // 定义售楼处
salesOffice.clientList = [] // 缓存列表,用于存放订阅着的回调函数
salesOffice.listen = function(key, fn) {
if (!this.clientList[key]) { // 如果还没有订阅过此类消息,给该类消息创建一个缓存列表
this.clientList[key] = [] // 初始化
}
this.clientList[key].push(fn) // 订阅的消息添加进缓存列表中
}
salesOffice.trigger = function () { // 发布消息
var key = Array.prototype.shift.call(arguments) // 取出消息类型
var fns = this.clientList[key] // 取出该消息的对应的回调函数
if(!fns || fns.length === 0) { // 如果没有订阅过该消息直接返回
return false
}
for(var i=0, fn; fn = fns[i++]; ) {
fn.apply(this, arguments)
}
}
// test
salesOffice.listen('squareMeter88', function(price) {
console.log('价格= ' + price)
})
salesOffice.listen('squareMeter88', function(price) {
console.log('价格= ' + price)
})
salesOffice.listen('squareMeter90', function(price) {
console.log('价格= ' + price)
})
salesOffice.trigger('squareMeter88', 88)
salesOffice.trigger('squareMeter90', 90)
var event = {
list: [], // 用来存放缓存的订阅函数
listen: function(key, fn) {
if (!this.list[key]) {
this.list[key] = [] // 初始化一个数组
}
this.list[key].push(fn)
},
trigger: function() {
var key = Array.prototype.shift.call(arguments) // 取出参数中的第一kye
console.log(key)
var fns = this.list[key] // 拿出定订阅的缓存函数
if (!fns || fns.length === 0) return false // 判断是否存key值对应的缓存函数,不存在的话终止执行
this.list.forEach((fn) => { // 循环自调用每一个函数
fn.apply(this, arguments)
})
}
}
var event = {
list: [], // 用来存放缓存的订阅函数
listen: function(key, fn) {
if (!this.list[key]) {
this.list[key] = [] // 初始化一个数组
}
this.list[key].push(fn)
},
trigger: function() {
var key = Array.prototype.shift.call(arguments) // 取出参数中的第一kye
console.log(key)
var fns = this.list[key] // 拿出定订阅的缓存函数
if (!fns || fns.length === 0) return false // 判断是否存key值对应的缓存函数,不存在的话终止执行
this.list.forEach((fn) => { // 循环自调用每一个函数
fn.apply(this, arguments)
})
}
}
function installEvent(obj) {
for (var key in event ) {
obj[key] = event[key]
}
}
完整的发布订阅模式
// 手写一个发布订阅
var event = {
list: [], // 用来存储订阅的函数
listen: function(key, fn) {
if (!this.list[key]) {
this.list[key] = []
}
if (!fn) {
return false // 如果没有传入具体的回到函数,则直接返回false
}
this.list[key].push(fn)
},
trigger: function() {
//
var key = Array.prototype.shift.call(arguments)
var fns = this.list[key]
if (!fns || fns.length === 0) return false
fns.forEach( (fn) => {
fn.apply(this, arguments)
})
},
remove: function(key, fn) {
var fns = this.list[key]
if(!fns) { // 如果key对应的消息被人订阅,则直接返回
return false
}
if (!fn) { // 如果没有具体的传入具体的回调函数,则表示需要取消所有的key对应的消息所有订阅
console.log('执行')
fns && (fns.length = 0)
} else { // 传入取消
for(var l = fns.length - 1; l >=0; l-- ) {
var _fn = fns[l]
if( _fn === fn ) {
fns.splice(l, 1) // 删除订阅者的回调函数
}
}
}
}
}
function installEvent(obj) {
for(var key in event ) {
obj[key] = event[key]
}
}
全局模式下的发布订阅
var Event = (function() {
var clientList = {},
listen,
trigger,
remove
listen = function(key, fn) {
if (!clientList[key]) {
clientList[key] = []
}
clientList[key].push(fn)
}
trigger = function() {
var key = Array.prototype.shift.call(arguments)
var fns = clientList[key]
if (!fns || fns.length === 0 ) {
return false
}
// 循环遍历执行代码
fns.forEach( (fn) => {
fn.apply(this, arguments)
})
}
remove = function(key, fn) {
var fns = clientList[key]
if (!fns) { // 如果传入的key值中,没有具体的函数,直接返回
return false
}
if (!fn) { // 如果没有传入具体的回调函数,清空所有的key对应的函数
fns && (fns.length = 0)
} else {
// 存在fn ,需要找到这个fn,然后删除
for (var i = fns.length - 1; i >=0; i--) {
var _fn = fns[i]
if (_fn === fn) {
fns.splice(i, 1)
}
}
}
}
return {
clientList: clientList,
listen: listen,
trigger: trigger,
remove: remove
}
})()
ts 版本
// 发布订阅
class BusEvent {
public type: string
public fn: (...arg: any[]) => void
constructor(type: string, fn: (...args: any[]) => void) {
this.type = type
this.fn = fn
}
}
class Listen {
public listenrs = new Set<BusEvent>()
public add(type: string, fn: (...args: any[]) => void) {
const event = new BusEvent(type, fn)
this.listenrs.add(event)
return () => {
this.listenrs.delete(event)
}
}
public dispatch(type: string, ...arg: any[]) {
this.listenrs.forEach( item => {
if (item.type === type) {
item.fn(...arg)
}
})
}
public remove(type: string, fn: (...args: any[]) => void) {
const event = new BusEvent(type, fn)
this.listenrs.delete(event)
}
}
export const listen = new Listen()