Vue事件总线(EventBus)使用详细介绍

EventBus的简介

EventBus 又称为事件总线。在Vue中可以使用 EventBus 来作为沟通桥梁的概念,就像是所有组件共用相同的事件中心,可以向该中心注册发送事件或接收事件,所以组件都可以上下平行地通知其他组件,但也就是太方便所以若使用不慎,就会造成难以维护的“灾难”,因此才需要更完善的Vuex作为状态管理中心,将通知的概念上升到共享状态层次。

一、初始化
首先需要创建事件总线并将其导出,以便其它模块可以使用或者监听它。我们可以通过两种方式来处理。先来看第一种,新创建一个 .js 文件,比如 event-bus.js

// event-bus.js
import Vue from ‘vue’
export const EventBus = new Vue()
实质上EventBus是一个不具备 DOM 的组件,它具有的仅仅只是它实例方法而已,因此它非常的轻便。

另外一种方式,可以直接在项目中的 main.js 初始化 EventBus :

// main.js
Vue.prototype.$EventBus = new Vue()
注意,这种方式初始化的EventBus是一个全局的事件总线。稍后再来聊一聊全局的事件总线。

现在我们已经创建了 EventBus ,接下来你需要做到的就是在你的组件中加载它,并且调用同一个方法,就如你在父子组件中互相传递消息一样。

二、发送事件

假设你有两个Vue页面需要通信: A 和 B ,A页面 在按钮上面绑定了点击事件,发送一则消息,想=通知 B页面。



接下来,我们需要在 B页面 中接收这则消息。

三、接收事件


同理我们也可以在 B页面 向 A页面 发送消息。这里主要用到的两个方法:

// 发送消息
EventBus.$emit(channel: string, callback(payload1,…))

// 监听接收消息
EventBus.$on(channel: string, callback(payload1,…))
前面提到过,如果使用不善,EventBus会是一种灾难,到底是什么样的“灾难”了?大家都知道vue是单页应用,如果你在某一个页面刷新了之后,与之相关的EventBus会被移除,这样就导致业务走不下去。还要就是如果业务有反复操作的页面,EventBus在监听的时候就会触发很多次,也是一个非常大的隐患。这时候我们就需要好好处理EventBus在项目中的关系。通常会用到,在vue页面销毁时,同时移除EventBus事件监听。
移除事件监听者
如果想移除事件的监听,可以像下面这样操作:

import {
eventBus
} from ‘./event-bus.js’
EventBus.$off(‘aMsg’, {})
你也可以使用 EventBus.$off(‘aMsg’) 来移除应用内所有对此某个事件的监听。或者直接调用 EventBus.$off() 来移除所有事件频道,不需要添加任何参数 。

上面就是 EventBus 的使用方法,是不是很简单。上面的示例中我们也看到了,每次使用 EventBus 时都需要在各组件中引入 event-bus.js 。事实上,我们还可以通过别的方式,让事情变得简单一些。那就是创建一个全局的 EventBus 。接下来的示例向大家演示如何在Vue项目中创建一个全局的 EventBus 。

全局EventBus

它的工作原理是发布/订阅方法,通常称为 Pub/Sub 。

创建全局EventBus

var EventBus = new Vue();

Object.defineProperties(Vue.prototype, {
$bus: {
get: function () {
return EventBus
}
}
})
在这个特定的总线中使用两个方法$on和$emit。一个用于创建发出的事件,它就是$emit;另一个用于订阅$on:

var EventBus = new Vue();

this.$bus.$emit(‘nameOfEvent’, { … pass some event data …});

this.$bus.$on(‘nameOfEvent’,($event) => {
// …
})
然后我们可以在某个Vue页面使用this.$bus.$emit(“sendMsg”, ‘我是web秀’);,另一个Vue页面使用

this.$bus.$on(‘updateMessage’, function(value) {
console.log(value); // 我是web秀
})
同时也可以使用this.$bus.$off(‘sendMsg’)来移除事件监听。

总结

本文主要通过简单的实例学习了Vue中有关于 EventBus 相关的知识点。主要涉及了 EventBus 如何实例化,又是如何通过 $emit 发送频道信号,又是如何通过 $on 来接收频道信号。最后简单介绍了如何创建全局的 EventBus 。从实例中我们可以了解到, EventBus 可以较好的实现兄弟组件之间的数据通讯。

如何监听html外链资源加载失败

GlobalEventHandlers.onerror
混合事件 GlobalEventHandlers 的 onerror 属性是用于处理 error (en-US) 的事件
Error事件的事件处理程序,在各种目标对象的不同类型错误被触发:

当JavaScript运行时错误(包括语法错误)发生时,window会触发一个ErrorEvent接口的error事件,并执行window.onerror()。
当一项资源(如img或script)加载失败,加载资源的元素会触发一个Event接口的error事件,并执行该元素上的onerror()处理函数。这些error事件不会向上冒泡到window,不过(至少在Firefox中)能被单一的window.addEventListener (en-US)捕获。
加载一个全局的error事件处理函数可用于自动收集错误报告。

window.onerror
window.onerror = function(message, source, lineno, colno, error) { … }
函数参数:

message:错误信息(字符串)。可用于HTML onerror=””处理程序中的event。
source:发生错误的脚本URL(字符串)
lineno:发生错误的行号(数字)
colno:发生错误的列号(数字)
error:Error对象(对象)
若该函数返回true,则阻止执行默认事件处理函数。

window.addEventListener(‘error’)
window.addEventListener(‘error’, function(event) { … })
ErrorEvent 类型的event包含有关事件和错误的所有信息。

element.onerror
element.onerror = function(event) { … }
element.onerror使用单一Event参数的函数作为其处理函数。

javascript的for of和for in的区别?

先说结论:

推荐在循环对象属性的时候,使用for…in,在遍历数组的时候的时候使用for…of。

for…in循环出的是key,for…of循环出的是value

注意,for…of是ES6新引入的特性。修复了ES5引入的for…in的不足

for…of不能循环普通的对象,需要通过和Object.keys()搭配使用

假设我们要遍历一个数组的valuelet aArray = [‘a’,123,{a:’1′,b:’2′}]

使用for…in循环:

for(let index in aArray){
console.log(`${aArray[index]}`);
}
使用for…of循环:

for(var value of aArray){
console.log(value);
}
咋一看好像好像只是写法不一样而已,那为什么说for…of修复了for…in的缺陷和不足。
假设我们往数组添加一个属性name:
aArray.name = ‘demo’,再分别查看上面写的两个循环:

for(let index in aArray){
console.log(`${aArray[index]}`); //Notice!!aArray.name也被循环出来了
}
for(var value of aArray){
console.log(value);
}
所以说,作用于数组的for-in循环除了遍历数组元素以外,还会遍历自定义属性。

for…of循环不会循环对象的key,只会循环出数组的value,因此for…of不能循环遍历普通对象,对普通对象的属性遍历推荐使用for…in

如果实在想用for…of来遍历普通对象的属性的话,可以通过和Object.keys()搭配使用,先获取对象的所有key的数组
然后遍历:

var student={
name:’wujunchuan’,
age:22,
locate:{
country:’china’,
city:’xiamen’,
school:’XMUT’
}
}
for(var key of Object.keys(student)){
//使用Object.keys()方法获取对象key的数组
console.log(key+”: “+student[key]);
}

惊群效应是什么

惊群效应是什么
惊群效应(thundering herd)是指多进程(多线程)在同时阻塞等待同一个事件的时候(休眠状态),如果等待的这个事件发生,那么他就会唤醒等待的所有进程(或者线程),但是最终却只能有一个进程(线程)获得这个时间的“控制权”,对该事件进行处理,而其他进程(线程)获取“控制权”失败,只能重新进入休眠状态,这种现象和性能浪费就叫做惊群效应。

惊群效应消耗了什么
Linux 内核对用户进程(线程)频繁地做无效的调度、上下文切换等使系统性能大打折扣。上下文切换(context switch)过高会导致 CPU 像个搬运工,频繁地在寄存器和运行队列之间奔波,更多的时间花在了进程(线程)切换,而不是在真正工作的进程(线程)上面。直接的消耗包括 CPU 寄存器要保存和加载(例如程序计数器)、系统调度器的代码需要执行。间接的消耗在于多核 cache 之间的共享数据。
为了确保只有一个进程(线程)得到资源,需要对资源操作进行加锁保护,加大了系统的开销。目前一些常见的服务器软件有的是通过锁机制解决的,比如 Nginx(它的锁机制是默认开启的,可以关闭);还有些认为惊群对系统性能影响不大,没有去处理,比如 Lighttpd。

pm2是怎么工作的吗 pm2工作原理

Node Cluster
熟悉 js 的朋友都知道,js 是单线程的,在 Node 中,采用的是 多进程单线程 的模型。由于单线程的限制,在多核服务器上,我们往往需要启动多个进程才能最大化服务器性能。

Node 在 V0.8 版本之后引入了 cluster模块,通过一个主进程 (master) 管理多个子进程 (worker) 的方式实现集群。

通信
Node中主进程和子进程之间通过进程间通信 (IPC) 实现进程间的通信,进程间通过 send 方法发送消息,监听 message 事件收取信息,这是 cluster模块 通过集成 EventEmitter 实现的。

负载均衡
了解 cluster 的话会知道,子进程是通过 cluster.fork() 创建的。在 linux 中,系统原生提供了 fork 方法,那么为什么 Node 选择自己实现 cluster模块 ,而不是直接使用系统原生的方法?主要的原因是以下两点:

fork的进程监听同一端口会导致端口占用错误
fork的进程之间没有负载均衡,容易导致惊群现象
在 cluster模块 中,针对第一个问题,通过判断当前进程是否为 master进程,若是,则监听端口,若不是则表示为 fork 的 worker进程,不监听端口。

针对第二个问题,cluster模块 内置了负载均衡功能,master进程 负责监听端口接收请求,然后通过调度算法(默认为 Round-Robin,可以通过环境变量 NODE_CLUSTER_SCHED_POLICY 修改调度算法)分配给对应的 worker进程。

pm2的实现
pm2 基于 cluster模块 进行了封装,它能自动监控进程状态、重启进程、停止不稳定进程、日志存储等。利用 pm2 时,可以在不修改代码的情况下实现负载均衡集群。

这篇文章我们要关注的是 pm2 的 Satan进程、God Deamon守护进程 以及 两者之间的 进程间远程调用RPC。

撒旦(Satan),主要指《圣经》中的堕天使(也称堕天使撒旦),被看作与上帝的力量相对的邪恶、黑暗之源,是God的对立面。

其中 Satan.js 提供程序的退出、杀死等方法,God.js 负责维持进程的正常运行,God进程启动后一直运行,相当于 cluster 中的 Master进程,维持 worker 进程的正常运行。

RPC 是指远程过程调用协议,具体释义就不细讲了,感兴趣的自行查阅。在 pm2 中用于同一机器上的不同进程之间的方法调用。