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入门《Oracle介绍》第一章1-2 Oracle 实例
Oracle实例:是后台进程和内存结构的集合 一.内存结构 1.Oracle 实例启动时分配系统全局区 a.数据库信息存储于SGA,由多个数据库进程共享 1.共享池是对SQL.PL/SQL程序进行语法 ...
- ajax+ashx:实现文件的批量导出
背景: 最近公司有一个需求,就是实现excle的批量导出(一次性导出多个excle). 实现方式: 想到的实现方式: 1.发起一个导出请求,然后批量生产需要导出的excle文件,最后将文件生成一个压缩 ...
- 使用Nexus2.x为Maven3.x搭建私服构件仓库
前言 在笔者的前一篇博文<Use Maven3.x>中,笔者详细的讲解了如何通过使用Maven3.x来构建及管理你的项目.其中笔者提到过些关于私服的概念,但却没有明确的对私服做出详细的阐述 ...
- jsp-servlet 的相关请求路径问题 —url
jsp-servlet 的相关请求路径问题 —url 本文章主要解决的几方面问题如下: 常见涉及路径元素: jsp页面请求和servlet请求转发.重定向的关系 如何避免下一步请求受上一步请求在UR ...
- python之初识网络
一. C/S架构:客户端(client)/服务端(server)架构 B/S架构:浏览器(browser) / 服务端(server)架构 软件cs架构: 浏览器,qq,微信等等 硬件cs架构:打印机 ...
- python联系题1
一.有四个数字:1.2.3.4,能组成多少个互不相同且无重复数字的三位数?各是多少? 程序分析:可填在百位.十位.个位的数字都是1.2.3.4.组成所有的排列后再去 掉不满足条件的排列. # _*_ ...
- MinGW编译Mongo-CXX-Driver
8. mongo-cxx-driver pacman -S mingw-w64-x86_64-cyrus-sasl pacman -S mingw-w64-x86_64-extra-cmake-mod ...
- Java字符串占位符(commons-text)替换(转载)
Java字符串占位符(commons-text)替换 https://blog.csdn.net/varyall/article/details/83651798 <dependency> ...
- Linux 学习笔记之超详细基础linux命令 Part 14
Linux学习笔记之超详细基础linux命令 by:授客 QQ:1033553122 ---------------------------------接Part 13---------------- ...
- loadrunner 运行场景-常见Graph简介
运行场景-常见Graph简介 by:授客 QQ:1033553122 A. Web Resource Graphs 1. 概述 a) Hits per Second Graph Hits ...