MetaMask/safe-event-emitter
https://github.com/MetaMask/safe-event-emitter
safe-event-emitter
An EventEmitter
that isolates the emitter from errors in handlers. If an error is thrown in a handler it is caught and re-thrown inside of a setTimeout
so as to not interupt the emitter's code flow.
是一个将emitter与处理程序handlers中的错误隔离的事件发射器。如果在处理程序中抛出错误,就会被捕获并在setTimeout中重新抛出,以便不会中断发射器的代码流
API is the same as EventEmitter
.
usage
const SafeEventEmitter = require('safe-event-emitter') const ee = new SafeEventEmitter()
ee.on('boom', () => { throw new Error() })
ee.emit('boom') // no error here // error is thrown after setTimeout
safe-event-emitter/index.js
const util = require('util')
const EventEmitter = require('events/') var R = typeof Reflect === 'object' ? Reflect : null //Reflect是对象则为R,否则R为null
var ReflectApply = R && typeof R.apply === 'function' //当R不为null且R.apply是函数时,ReflectApply为R.apply函数,否则就是定义的ReflectApply函数
? R.apply
: function ReflectApply(target, receiver, args) {
return Function.prototype.apply.call(target, receiver, args);
} module.exports = SafeEventEmitter function SafeEventEmitter() {
EventEmitter.call(this)
} util.inherits(SafeEventEmitter, EventEmitter) SafeEventEmitter.prototype.emit = function (type) {//事件触发函数
// copied from https://github.com/Gozala/events/blob/master/events.js
// modified lines are commented with "edited:"
var args = [];
for (var i = ; i < arguments.length; i++) args.push(arguments[i]); //将传入的参数push进数组args
var doError = (type === 'error'); //即事件的类型是否为“error” var events = this._events;
if (events !== undefined)//当事件被定义了时,即调用过on()进行监听
doError = (doError && events.error === undefined); //事件为error但是events.error没有定义doError才返回true
else if (!doError) //如果不是error事件则返回false
return false; // If there is no 'error' event listener then throw.
if (doError) { //如果为error事件
var er;
if (args.length > ) //且有参数传入
er = args[]; //第一个参数应该为Error
if (er instanceof Error) {//name就将错误抛出
// Note: The comments on the `throw` lines are intentional, they show
// up in Node's output if this results in an unhandled exception.
throw er; // Unhandled 'error' event
}
// At least give some kind of context to the user 否则就说明没有定义Error,那么下面就会定义相应的错误抛出
var err = new Error('Unhandled error.' + (er ? ' (' + er.message + ')' : ''));
err.context = er;
throw err; // Unhandled 'error' event
} var handler = events[type];//得到on()监听时定义的回调函数 if (handler === undefined)//如果回调没定义则返回false
return false; if (typeof handler === 'function') {//如果定义了则调用下面的safeApply(回调函数,上下文环境,参数)
// edited: using safeApply
safeApply(handler, this, args);
} else { //如果回调不是一个函数,而是一个函数数组,则调用arrayClone()
var len = handler.length;
var listeners = arrayClone(handler, len);
for (var i = ; i < len; ++i)
// edited: using safeApply
safeApply(listeners[i], this, args);
} return true;
} function safeApply(handler, context, args) {//就是在context这个上下文环境中,将相应的args参数传给handler回调函数,对回调函数进行调用
try {
ReflectApply(handler, context, args)
} catch (err) { //特别之处就在于在调用回调过程中如果出错了,错误先使用setTimeout压入堆栈,在整个回调函数调用完成后才抛出
// throw error after timeout so as not to interupt the stack
setTimeout(() => {
throw err
})
}
} function arrayClone(arr, n) {
var copy = new Array(n);
for (var i = ; i < n; ++i)
copy[i] = arr[i];
return copy;
}
补充知识:
Reflect 是一个内置的对象,它提供拦截 JavaScript 操作的方法。这些方法与处理器对象的方法相同。Reflect
不是一个函数对象,因此它是不可构造的。
与大多数全局对象不同,Reflect
没有构造函数。你不能将其与一个new运算符一起使用,或者将Reflect
对象作为一个函数来调用。Reflect
的所有属性和方法都是静态的(就像Math
对象)。
可以理解为:有这么一个全局对象,上面直接挂载了对象的某些特殊方法,这些方法可以通过Reflect.apply这种形式来使用,当然所有方法都是可以在 Object 的原型链中找到的。
使用reflect的好处
引自知乎专栏:ES6 Reflect
Reflect上面的一些方法并不是专门为对象设计的,比如Reflect.apply方法,它的参数是一个函数,如果使用Object.apply(func)会让人感觉很奇怪。
用一个单一的全局对象去存储这些方法,能够保持其它的JavaScript代码的整洁、干净。不然的话,这些方法可能是全局的,或者要通过原型来调用。
将一些命令式的操作如delete,in等使用函数来替代,这样做的目的是为了让代码更加好维护,更容易向下兼容;也避免出现更多的保留字。
方法:
Reflect对象提供以下静态函数,它们具有与处理器对象方法相同的名称。这些方法中的一些与 Object 上的对应方法相同。
Reflect.apply() 对一个函数进行调用操作,同时可以传入一个数组作为调用参数。和 Function.prototype.apply() 功能类似。
Reflect.construct() 对构造函数进行 new 操作,相当于执行 new target(...args)。
Reflect.defineProperty() 和 Object.defineProperty() 类似。
Reflect.deleteProperty() 作为函数的delete操作符,相当于执行 delete target[name]。
Reflect.enumerate() 该方法会返回一个包含有目标对象身上所有可枚举的自身字符串属性以及继承字符串属性的迭代器,for...in 操作遍历到的正是这些属性。
Reflect.get() 获取对象身上某个属性的值,类似于 target[name]。
Reflect.getOwnPropertyDescriptor() 类似于 Object.getOwnPropertyDescriptor()。
Reflect.getPrototypeOf() 类似于 Object.getPrototypeOf()。
Reflect.has() 判断一个对象是否存在某个属性,和 in 运算符 的功能完全相同。
Reflect.isExtensible() 类似于 Object.isExtensible().
Reflect.ownKeys() 返回一个包含所有自身属性(不包含继承属性)的数组。
Reflect.preventExtensions() 类似于 Object.preventExtensions()。返回一个Boolean。
Reflect.set() 将值分配给属性的函数。返回一个Boolean,如果更新成功,则返回true。
Reflect.setPrototypeOf() 类似于 Object.setPrototypeOf()。
MetaMask/safe-event-emitter的更多相关文章
- Event Bus & Event Emitter
Event Bus & Event Emitter Event Bus https://code.luasoftware.com/tutorials/vuejs/parent-call-chi ...
- MetaMask/obs-store
https://github.com/MetaMask/obs-store ObservableStore ObservableStore is a synchronous in-memory sto ...
- metamask源码学习-controller-transaction
()metamask-extension/app/scripts/controllers/transactions Transaction Controller is an aggregate of ...
- Guide to Porting MetaMask to a New Environment
https://github.com/MetaMask/metamask-extension/blob/develop/docs/porting_to_new_environment.md MetaM ...
- metamask源码学习-controllers-network
https://github.com/MetaMask/metamask-extension/tree/master/app/scripts/controllers/network metamask- ...
- Christmas Trees, Promises和Event Emitters
今天有同事问我下面这段代码是什么意思: var MyClass = function() { events.EventEmitter.call(this); // 这行是什么意思? }; util.i ...
- UVW源码漫谈(番外篇)—— Emitter
这两天天气凉了,苏州这边连续好几天都是淅淅沥沥的下着小雨,今天天气还稍微好点.前两天早上起来突然就感冒了,当天就用了一卷纸,好在年轻扛得住,第二天就跟没事人似的.在这里提醒大家一下,天气凉了,睡凉席的 ...
- 理解Nodejs的Event Loop
Node的“event loop”主要是用来处理高输出量的.这很神奇,这也是为什么node可以在单线程的情况下同时处理很多的后台操作.本文就会集中讲述event loop是怎么运行的,这样你可以可以使 ...
- CustomEvent & Event
CustomEvent & Event js 自定义事件 const event = new CustomEvent(typeArg, customEventInit); // add an ...
- EventBus / Event Bus
EventBus / Event Bus EventEmitter / Event Emitter https://greenrobot.org/eventbus/documentation/ htt ...
随机推荐
- oracle 外连接以及用on和where 的区别
Oracle 外连接(OUTER JOIN)包括以下: 左外连接(左边的表不加限制) 右外连接(右边的表不加限制) 全外连接(左右两表都不加限制) 对应SQL:LEFT/RIGHT/FULL OUT ...
- HDFS的副本存放策略(全)
HDFS的副本存放策略 HDFS作为Hadoop中的一个分布式文件系统,而且是专门为它的MapReduce设计,所以HDFS除了必须满足自己作为分布式文件系统的高可靠性外,还必须为MapReduc ...
- hive的行列转换
行转列(把多个行合并) 比如把: id tag 1 12 1 23 2 67 2 78 2 76 行转列之后: id tag 1 12,23 2 67,78,76 使用函数为:concat_w ...
- canvas-0trasform.html
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8&quo ...
- 纯css抖动效果
HTML: <button class="shake">按钮</button> CSS: .shake{ width: 120px; height: 33p ...
- 【读书笔记】iOS-Settings Bundle
一,打开工程--->右键--->Add File--->iOS-->Resource-->Settings Bundle. 二,会弹出如下对话框---->Creat ...
- 安卓开发_startActivityForResult的详细用法
一个需求:一个activity到另一个activity进行一些设置,返回第一个activity的时候 获取第二个activity设置的数据 百度了一下,发现startActivityForResult ...
- vue路由的配置
一.准备工作 1安装vue-cli npm install vue-cli -g 2检查是否安装成功 vue -V(大写V) 3初始化一个新的项目 vue init webpack vue-dem ...
- springcloud 入门 10 (eureka高可用)
eureka高可用: 说白了,就是加一个实例作为原实例的备份,然后一起对外提供服务.这样可以保证在一台机器宕机的时候,整个系统不会死掉.保证其继续对外服务. eureka的集群化: 服务注册中心Eur ...
- C# 异步编程4 async与await 异步程序开发
随着C#异步程序开发系列的深入,你会发现编写异步程序越发简单.事物的发展就是这样的规律,从简单到复杂再到简单. 在C# 5.0中我们可以通过async与await关键字实现快捷的异步程序开发,如下: ...