从node异步编程解决方案提及吧:
- 事宜宣布/定阅形式
- Promise/deferred形式
- 流程掌握库
事宜宣布/定阅形式
事宜监听器形式是一种普遍运用于异步编程的形式,是回调函数的事宜话,又称宣布/定阅形式。
重要完成的几个功用包含
- on
- remove
- once
- emit
废话少说,我们来简朴的完成一个事宜监听函数吧
起首建立一个eventEmitter函数
function EventEmitter() {
// 用Object.create(null)替代空对象{}
// 优点是无杂质,不继续原型链
// _events来保留视察着行列的信息
this._events = Object.create(null);
}
由于过量的侦听器占用大批内存,致使内存走漏,所以侦听器的个数平常不会凌驾10个,不然会有warnning正告⚠️
接下来是一些默许的设置
// 默许最多的绑定次数
EventEmitter.defaultMaxListeners = 10;
// 同on要领
EventEmitter.prototype.addListener = EventEmitter.prototype.on;
// 返回监听的事宜名
EventEmitter.prototype.eventNames = function () {
return Object.keys(this._events);
};
// 设置最大监听数
EventEmitter.prototype.setMaxListeners = function (n) {
this._count = n;
};
// 返回监听数
EventEmitter.prototype.getMaxListeners = function () {
return this._count ? this._count : this.defaultMaxListeners;
};
接下来是on函数的完成
EventEmitter.prototype.on = function (type, cb, flag) {
// 不是newListener 就应该让newListener实行以下
if (type !== 'newListener') {
this._events['newListener'] && this._events['newListener'].forEach(listener => {
listener(type);
});
}
if (this._events[type]) {
// 依据传入的flag来决定是向前照样向后增加
if (flag) {
this._events[type].unshift(cb);
} else {
this._events[type].push(cb);
}
} else {
this._events[type] = [cb];
}
// 监听的事宜不能凌驾了设置的最大监听数
if (this._events[type].length === this.getMaxListeners()) {
console.warn('正告-监听器Number过大');
}
};
剖析:
on函数是帮定的初始函数,起首推断是不是是初次举行侦听,假如是的话,先举行一遍初始化函数
接下来在——events行列里找到指针为type的处所,依据flag推断是在行列尾照样头到场callback函数
接下来是once监听一次的完成要领
// 监听一次
EventEmitter.prototype.once = function (type, cb, flag) {
// 先绑定,调用后删除
function wrap() {
cb(...arguments);
this.removeListener(type, wrap);
}
// 自定义属性
wrap.listen = cb;
this.on(type, wrap, flag);
};
剖析:
完成为在callback上包装一层remove操纵,再当作一个新的callback传入on函数
如许的的话在初次实行回调的时刻就会实行remove操纵,到达实行一次就删除的操纵
接下来是remove函数,删除一个type的侦听器
EventEmitter.prototype.removeListener = function (type, cb) {
if (this._events[type]) {
this._events[type] = this._events[type].filter(listener => {
return cb !== listener && cb !== listener.listen;
});
}
};
剖析:
传入type和要删除的callback,对type标记的数组举行 filter操纵,假如cb cb === listener则过滤掉
删除一切
EventEmitter.prototype.removeAllListener = function () {
this._events = Object.create(null);
};
接下来是宣布函数 emit
EventEmitter.prototype.emit = function (type, ...args) {
if (this._events[type]) {
this._events[type].forEach(listener => {
listener.call(this, ...args);
});
}
};
剖析:
也比较直观,假如events内里存在type的监听器行列,则行列里的每一个回调都实行一遍,而且用call函数绑定this和arg
完全代码
//EventEmitter.js
function EventEmitter() {
// 用Object.create(null)替代空对象{}
// 优点是无杂质,不继续原型链的东东
this._events = Object.create(null);
}
// 默许最多的绑定次数
EventEmitter.defaultMaxListeners = 10;
// 同on要领
EventEmitter.prototype.addListener = EventEmitter.prototype.on;
// 返回监听的事宜名
EventEmitter.prototype.eventNames = function () {
return Object.keys(this._events);
};
// 设置最大监听数
EventEmitter.prototype.setMaxListeners = function (n) {
this._count = n;
};
// 返回监听数
EventEmitter.prototype.getMaxListeners = function () {
return this._count ? this._count : this.defaultMaxListeners;
};
// 监听
EventEmitter.prototype.on = function (type, cb, flag) {
// 默许值,假如没有_events的话,就给它建立一个
if (!this._events) {
this._events = Object.create(null);
}
// 不是newListener 就应该让newListener实行以下
if (type !== 'newListener') {
this._events['newListener'] && this._events['newListener'].forEach(listener => {
listener(type);
});
}
if (this._events[type]) {
// 依据传入的flag来决定是向前照样向后增加
if (flag) {
this._events[type].unshift(cb);
} else {
this._events[type].push(cb);
}
} else {
this._events[type] = [cb];
}
// 监听的事宜不能凌驾了设置的最大监听数
if (this._events[type].length === this.getMaxListeners()) {
console.warn('正告-正告-正告');
}
};
// 向前增加
EventEmitter.prototype.prependListener = function (type, cb) {
this.on(type, cb, true);
};
EventEmitter.prototype.prependOnceListener = function (type, cb) {
this.once(type, cb, true);
};
// 监听一次
EventEmitter.prototype.once = function (type, cb, flag) {
// 先绑定,调用后删除
function wrap() {
cb(...arguments);
this.removeListener(type, wrap);
}
// 自定义属性
wrap.listen = cb;
this.on(type, wrap, flag);
};
// 删除监听范例
EventEmitter.prototype.removeListener = function (type, cb) {
if (this._events[type]) {
this._events[type] = this._events[type].filter(listener => {
return cb !== listener && cb !== listener.listen;
});
}
};
EventEmitter.prototype.removeAllListener = function () {
this._events = Object.create(null);
};
// 返回一切的监听范例
EventEmitter.prototype.listeners = function (type) {
return this._events[type];
};
// 宣布
EventEmitter.prototype.emit = function (type, ...args) {
if (this._events[type]) {
this._events[type].forEach(listener => {
listener.call(this, ...args);
});
}
};
module.exports = EventEmitter;
我的博客行将同步至腾讯云+社区,约请人人一同入驻:https://cloud.tencent.com/dev…