Skip to content

Commit

Permalink
Added maxListeners to a config object, added priority level to listeners
Browse files Browse the repository at this point in the history
Exposed LOW_PRIORITY, NORMAL_PRIORITY, and HIGH_PRIORITY on the Emitter object. Added maxListeners and maxOnceListeners that can be set using a config object when instantiating an Emitter. Renamed id to namespace.
  • Loading branch information
mdaemon-technologies committed Apr 4, 2024
1 parent f214161 commit ef8d588
Show file tree
Hide file tree
Showing 8 changed files with 299 additions and 63 deletions.
110 changes: 110 additions & 0 deletions .npmignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,110 @@
# Logs
logs
*.log
npm-debug.log*
yarn-debug.log*
yarn-error.log*
lerna-debug.log*

# Diagnostic reports (https://nodejs.org/api/report.html)
report.[0-9]*.[0-9]*.[0-9]*.[0-9]*.json

# Runtime data
pids
*.pid
*.seed
*.pid.lock

# Directory for instrumented libs generated by jscoverage/JSCover
lib-cov

# Coverage directory used by tools like istanbul
coverage
*.lcov

# nyc test coverage
.nyc_output

# Grunt intermediate storage (https://gruntjs.com/creating-plugins#storing-task-files)
.grunt

# Bower dependency directory (https://bower.io/)
bower_components

# node-waf configuration
.lock-wscript

# Compiled binary addons (https://nodejs.org/api/addons.html)
build/Release

# Dependency directories
node_modules/
jspm_packages/

# TypeScript v1 declaration files
typings/

# TypeScript cache
*.tsbuildinfo

# Optional npm cache directory
.npm

# Optional eslint cache
.eslintcache

# Microbundle cache
.rpt2_cache/
.rts2_cache_cjs/
.rts2_cache_es/
.rts2_cache_umd/

# Optional REPL history
.node_repl_history

# Output of 'npm pack'
*.tgz

# Yarn Integrity file
.yarn-integrity

# dotenv environment variables file
.env
.env.test

# parcel-bundler cache (https://parceljs.org/)
.cache

# Next.js build output
.next

# Nuxt.js build / generate output
.nuxt

# Gatsby files
.cache/
# Comment in the public line in if your project uses Gatsby and *not* Next.js
# https://nextjs.org/blog/next-9-1#public-directory-support
# public

# vuepress build output
.vuepress/dist

# Serverless directories
.serverless/

# FuseBox cache
.fusebox/

# DynamoDB Local files
.dynamodb/

# TernJS port file
.tern-port

src/
rollup.config.js
package-lock.json
.gitattributes
.gitignore
.github
21 changes: 20 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,11 @@ The "emitter" provides pub/sub options
* }
*/
const emitter = new Emitter();
// maxListeners and maxOnceListeners default to 50 and are immutable once set
const emitter = new Emitter({
maxListeners: 20,
maxOnceListeners: 40
});
emitter.on("test", "namespace", (input) => {
console.log(input);
Expand Down Expand Up @@ -97,6 +101,21 @@ The "emitter" provides pub/sub options
emitter.emit("test", "nothing will be logged");
// a priority property can be added to the end of the paramters
emitter.on("test3", "namespace", () => {
console.log("this will be logged last");
}, Emitter.LOW_PRIORITY);
emitter.on("test3", "namespace", () => {
console.log("this will be logged first");
}, Emitter.HIGH_PRIORITY);
emitter.emit("test3");
// this will be logged first
// this will be logged last
// once registrations do not have a priority, because the event will only execute once
```
# License #
Expand Down
2 changes: 1 addition & 1 deletion dist/emitter.cjs
Original file line number Diff line number Diff line change
@@ -1 +1 @@
"use strict";const t={string:function(t){return"string"==typeof t},object:function(t){return"object"==typeof t&&null!==t&&!Array.isArray(t)},array:function(t){return Array.isArray(t)},bool:function(t){return"boolean"==typeof t},number:function(t){return"number"==typeof t},func:function(t){return"function"==typeof t},nul:function(t){return null===t},undef:function(t){return void 0===t||void 0===t}};function e(t,e,n){this.name=t,this.id=e,this.func=n}module.exports=function(){const n=[],r=[],i=(t,e)=>{let r=n.length;for(;r;)if(r-=1,n[r].name===t&&n[r].id===e)return r;return-1};this.register=(r,s,u)=>{if(!r)return;let o=u;if(t.func(s))if(t.string(o)){const t=o;o=s,s=t}else o=s,s="all";const f=i(r,s),l=new e(r,s,o);-1===f?n.push(l):n[f]=l},this.on=this.register,this.subscribe=this.register,this.once=(t,n)=>{if(!t)return;const i=new e(t,"",n);r.push(i)},this.onMany=(t,e)=>{e&&Object.keys(e).forEach((n=>{this.on(n,t,e[n])}))},this.unregister=(t,e)=>{if(!t)return;let s=0;if("all"!==(e=e||"all"))s=i(t,e),-1!==s&&n.splice(s,1);else{for(s=n.length;s;)s-=1,n[s].name===t&&"all"===n[s].id&&n.splice(s,1);for(s=r.length;s;)s-=1,r[s].name===t&&r.splice(s,1)}},this.off=this.unregister,this.unsubscribe=this.unregister,this.offAll=t=>{let e=n.length;for(;e;)e-=1,n[e].id===t&&n.splice(e,1)},this.trigger=(t,e)=>{const i=(t=>{const e=[];for(let r=0,i=n.length;r<i;r+=1)n[r].name===t&&e.push(n[r]);return e})(t);for(let n=0,r=i.length;n<r;n+=1)i[n].func(e,t);let s=r.length;for(;s;)s-=1,r[s].name===t&&(r[s].func(e,t),r.splice(s,1))},this.emit=this.trigger,this.publish=this.trigger,this.propagate=(t,e)=>{this.trigger(e,t)},this.isRegistered=(t,e)=>{e=e||"all";let i=n.length;for(;i;)if(i-=1,n[i].id===e&&n[i].name===t)return!0;for(i=r.length;i;)if(i-=1,r[i].name===t)return!0;return!1}};
"use strict";const e={string:function(e){return"string"==typeof e},object:function(e){return"object"==typeof e&&null!==e&&!Array.isArray(e)},array:function(e){return Array.isArray(e)},bool:function(e){return"boolean"==typeof e},number:function(e){return"number"==typeof e},func:function(e){return"function"==typeof e},nul:function(e){return null===e},undef:function(e){return void 0===e||void 0===e}};function t(t,n,r,i){this.name=t,this.namespace=n,this.func=r,this.priority=e.number(i)?i:1}function n(n){this.config={},Object.defineProperty(this.config,"maxListeners",{value:n&&"number"==typeof n.maxListeners?n.maxListeners:50,writable:!1,enumerable:!0}),Object.defineProperty(this.config,"maxOnceListeners",{value:n&&"number"==typeof n.maxOnceListeners?n.maxOnceListeners:50,writable:!1,enumerable:!0});const r=[],i=[],s=e=>r.filter((t=>t.name===e)).length>=this.config.maxListeners,o=e=>i.filter((t=>t.name===e)).length>=this.config.maxListeners,a=(e,t)=>{let n=r.length;for(;n;)if(n-=1,r[n].name===e&&r[n].namespace===t)return n;return-1};this.register=(n,i,o,f)=>{if(!n)return;if(void 0!==f&&!e.number(f))throw new Error("priority must be a number");if(e.func(i))if(e.string(o)){const e=o;o=i,i=e}else e.number(o)&&(f=o),o=i,i="all";const u=a(n,i),l=new t(n,i,o,f);-1===u?s(n)?console.warn(`Max listeners reached for event ${n}`):r.push(l):r[u]=l,r.sort(((e,t)=>e.priority===t.priority?0:e.priority<t.priority?1:-1))},this.on=this.register,this.subscribe=this.register,this.once=(e,n,r)=>{if(!e)return;const s=new t(e,"",n,r);o(e)?console.warn(`Max once listeners reached for event ${e}`):i.push(s),i.sort(((e,t)=>e.priority===t.priority?0:e.priority>t.priority?1:-1))},this.onMany=(e,t)=>{t&&Object.keys(t).forEach((n=>{this.on(n,e,t[n])}))},this.unregister=(e,t)=>{if(!e)return;let n=0;if("all"!==(t=t||"all"))n=a(e,t),-1!==n&&r.splice(n,1);else{for(n=r.length;n;)n-=1,r[n].name===e&&"all"===r[n].namespace&&r.splice(n,1);for(n=i.length;n;)n-=1,i[n].name===e&&i.splice(n,1)}},this.off=this.unregister,this.unsubscribe=this.unregister,this.offAll=e=>{let t=r.length;for(;t;)t-=1,r[t].namespace===e&&r.splice(t,1)};this.trigger=(e,t)=>{const n=(e=>{const t=[];for(let n=0,i=r.length;n<i;n+=1)((r[n].name.indexOf("*")>-1||r[n].name.indexOf("?")>-1)&&new RegExp(r[n].name.replace(/\*/g,".*")).test(e)||r[n].name===e)&&t.push(r[n]);return t})(e);for(let r=0,i=n.length;r<i;r+=1)n[r].func(t,e);((e,t)=>{let n=i.length;for(;n;)n-=1,((i[n].name.indexOf("*")>-1||i[n].name.indexOf("?")>-1)&&new RegExp(i[n].name.replace(/\*/g,".*").replace(/\?/g,".")).test(e)||i[n].name===e)&&(i[n].func(t,e),i.splice(n,1))})(e,t)},this.emit=this.trigger,this.publish=this.trigger,this.propagate=(e,t)=>{this.trigger(t,e)},this.isRegistered=(e,t)=>{t=t||"all";let n=r.length;for(;n;)if(n-=1,r[n].namespace===t&&r[n].name===e)return!0;for(n=i.length;n;)if(n-=1,i[n].name===e)return!0;return!1}}n.HIGH_PRIORITY=2,n.NORMAL_PRIORITY=1,n.LOW_PRIORITY=0,module.exports=n;
2 changes: 1 addition & 1 deletion dist/emitter.mjs
Original file line number Diff line number Diff line change
@@ -1 +1 @@
const t={string:function(t){return"string"==typeof t},object:function(t){return"object"==typeof t&&null!==t&&!Array.isArray(t)},array:function(t){return Array.isArray(t)},bool:function(t){return"boolean"==typeof t},number:function(t){return"number"==typeof t},func:function(t){return"function"==typeof t},nul:function(t){return null===t},undef:function(t){return void 0===t||void 0===t}};function e(t,e,n){this.name=t,this.id=e,this.func=n}function n(){const n=[],r=[],i=(t,e)=>{let r=n.length;for(;r;)if(r-=1,n[r].name===t&&n[r].id===e)return r;return-1};this.register=(r,s,u)=>{if(!r)return;let o=u;if(t.func(s))if(t.string(o)){const t=o;o=s,s=t}else o=s,s="all";const f=i(r,s),l=new e(r,s,o);-1===f?n.push(l):n[f]=l},this.on=this.register,this.subscribe=this.register,this.once=(t,n)=>{if(!t)return;const i=new e(t,"",n);r.push(i)},this.onMany=(t,e)=>{e&&Object.keys(e).forEach((n=>{this.on(n,t,e[n])}))},this.unregister=(t,e)=>{if(!t)return;let s=0;if("all"!==(e=e||"all"))s=i(t,e),-1!==s&&n.splice(s,1);else{for(s=n.length;s;)s-=1,n[s].name===t&&"all"===n[s].id&&n.splice(s,1);for(s=r.length;s;)s-=1,r[s].name===t&&r.splice(s,1)}},this.off=this.unregister,this.unsubscribe=this.unregister,this.offAll=t=>{let e=n.length;for(;e;)e-=1,n[e].id===t&&n.splice(e,1)},this.trigger=(t,e)=>{const i=(t=>{const e=[];for(let r=0,i=n.length;r<i;r+=1)n[r].name===t&&e.push(n[r]);return e})(t);for(let n=0,r=i.length;n<r;n+=1)i[n].func(e,t);let s=r.length;for(;s;)s-=1,r[s].name===t&&(r[s].func(e,t),r.splice(s,1))},this.emit=this.trigger,this.publish=this.trigger,this.propagate=(t,e)=>{this.trigger(e,t)},this.isRegistered=(t,e)=>{e=e||"all";let i=n.length;for(;i;)if(i-=1,n[i].id===e&&n[i].name===t)return!0;for(i=r.length;i;)if(i-=1,r[i].name===t)return!0;return!1}}export{n as default};
const e={string:function(e){return"string"==typeof e},object:function(e){return"object"==typeof e&&null!==e&&!Array.isArray(e)},array:function(e){return Array.isArray(e)},bool:function(e){return"boolean"==typeof e},number:function(e){return"number"==typeof e},func:function(e){return"function"==typeof e},nul:function(e){return null===e},undef:function(e){return void 0===e||void 0===e}};function t(t,n,r,i){this.name=t,this.namespace=n,this.func=r,this.priority=e.number(i)?i:1}function n(n){this.config={},Object.defineProperty(this.config,"maxListeners",{value:n&&"number"==typeof n.maxListeners?n.maxListeners:50,writable:!1,enumerable:!0}),Object.defineProperty(this.config,"maxOnceListeners",{value:n&&"number"==typeof n.maxOnceListeners?n.maxOnceListeners:50,writable:!1,enumerable:!0});const r=[],i=[],s=e=>r.filter((t=>t.name===e)).length>=this.config.maxListeners,o=e=>i.filter((t=>t.name===e)).length>=this.config.maxListeners,a=(e,t)=>{let n=r.length;for(;n;)if(n-=1,r[n].name===e&&r[n].namespace===t)return n;return-1};this.register=(n,i,o,f)=>{if(!n)return;if(void 0!==f&&!e.number(f))throw new Error("priority must be a number");if(e.func(i))if(e.string(o)){const e=o;o=i,i=e}else e.number(o)&&(f=o),o=i,i="all";const l=a(n,i),u=new t(n,i,o,f);-1===l?s(n)?console.warn(`Max listeners reached for event ${n}`):r.push(u):r[l]=u,r.sort(((e,t)=>e.priority===t.priority?0:e.priority<t.priority?1:-1))},this.on=this.register,this.subscribe=this.register,this.once=(e,n,r)=>{if(!e)return;const s=new t(e,"",n,r);o(e)?console.warn(`Max once listeners reached for event ${e}`):i.push(s),i.sort(((e,t)=>e.priority===t.priority?0:e.priority>t.priority?1:-1))},this.onMany=(e,t)=>{t&&Object.keys(t).forEach((n=>{this.on(n,e,t[n])}))},this.unregister=(e,t)=>{if(!e)return;let n=0;if("all"!==(t=t||"all"))n=a(e,t),-1!==n&&r.splice(n,1);else{for(n=r.length;n;)n-=1,r[n].name===e&&"all"===r[n].namespace&&r.splice(n,1);for(n=i.length;n;)n-=1,i[n].name===e&&i.splice(n,1)}},this.off=this.unregister,this.unsubscribe=this.unregister,this.offAll=e=>{let t=r.length;for(;t;)t-=1,r[t].namespace===e&&r.splice(t,1)};this.trigger=(e,t)=>{const n=(e=>{const t=[];for(let n=0,i=r.length;n<i;n+=1)((r[n].name.indexOf("*")>-1||r[n].name.indexOf("?")>-1)&&new RegExp(r[n].name.replace(/\*/g,".*")).test(e)||r[n].name===e)&&t.push(r[n]);return t})(e);for(let r=0,i=n.length;r<i;r+=1)n[r].func(t,e);((e,t)=>{let n=i.length;for(;n;)n-=1,((i[n].name.indexOf("*")>-1||i[n].name.indexOf("?")>-1)&&new RegExp(i[n].name.replace(/\*/g,".*").replace(/\?/g,".")).test(e)||i[n].name===e)&&(i[n].func(t,e),i.splice(n,1))})(e,t)},this.emit=this.trigger,this.publish=this.trigger,this.propagate=(e,t)=>{this.trigger(t,e)},this.isRegistered=(e,t)=>{t=t||"all";let n=r.length;for(;n;)if(n-=1,r[n].namespace===t&&r[n].name===e)return!0;for(n=i.length;n;)if(n-=1,i[n].name===e)return!0;return!1}}n.HIGH_PRIORITY=2,n.NORMAL_PRIORITY=1,n.LOW_PRIORITY=0;export{n as default};
2 changes: 1 addition & 1 deletion dist/emitter.umd.js

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
{
"name": "@mdaemon/emitter",
"type": "module",
"version": "1.2.1",
"version": "1.3.0",
"description": "A basic event emitter / publish subscribe library used by MDaemon Webmail",
"main": "dist/emitter.cjs",
"module": "dist/emitter.mjs",
Expand Down
Loading

0 comments on commit ef8d588

Please sign in to comment.