Patch: added .once

67 views
Skip to first unread message

Peteris Krumins

unread,
Oct 12, 2010, 5:00:10 PM10/12/10
to nodejs
I added .once to EventEmitter, it works just like .on, except executes
the callback just once. It's really useful when you need to do
something just once. The name also looks good to me too, just two
chars longer than .on.

Here is the patch:

From 8bf8a2f8575210c642f4c804d121ab2d797bad48 Mon Sep 17 00:00:00 2001
From: Peteris Krumins <peteris...@gmail.com>
Date: Tue, 12 Oct 2010 23:52:26 +0300
Subject: [PATCH] added .once

---
lib/events.js | 10 +++++++++-
test/simple/test-event-emitter-once.js | 20 ++++++++++++++++++++
2 files changed, 29 insertions(+), 1 deletions(-)
create mode 100644 test/simple/test-event-emitter-once.js

diff --git a/lib/events.js b/lib/events.js
index e0480b0..cf9651a 100644
--- a/lib/events.js
+++ b/lib/events.js
@@ -76,6 +76,14 @@ EventEmitter.prototype.addListener = function
(type, listener) {

EventEmitter.prototype.on = EventEmitter.prototype.addListener;

+EventEmitter.prototype.once = function (type, listener) {
+ var self = this;
+ self.on(type, function g () {
+ self.removeListener(type, g);
+ listener.apply(this, arguments);
+ });
+};
+
EventEmitter.prototype.removeListener = function (type, listener) {
if ('function' !== typeof listener) {
throw new Error('removeListener only takes instances of
Function');
@@ -112,4 +120,4 @@ EventEmitter.prototype.listeners = function (type)
{
this._events[type] = [this._events[type]];
}
return this._events[type];
-};
\ No newline at end of file
+};
diff --git a/test/simple/test-event-emitter-once.js b/test/simple/test-
event-emitter-once.js
new file mode 100644
index 0000000..8639231
--- /dev/null
+++ b/test/simple/test-event-emitter-once.js
@@ -0,0 +1,20 @@
+common = require("../common");
+assert = common.assert
+var events = require('events');
+
+var e = new events.EventEmitter();
+var times_hello_emited = 0;
+
+e.once("hello", function (a, b) {
+ times_hello_emited++;
+});
+
+e.emit("hello", "a", "b");
+e.emit("hello", "a", "b");
+e.emit("hello", "a", "b");
+e.emit("hello", "a", "b");
+
+process.addListener("exit", function () {
+ assert.equal(1, times_hello_emited);
+});
+
--
1.7.0

Paul Querna

unread,
Oct 12, 2010, 5:05:22 PM10/12/10
to nod...@googlegroups.com
FWIW, I use a somewhat similar pattern in cast, adding a Once, but I
also added a .ensure():
http://github.com/cloudkick/cast/blob/master/lib/util/pubsub.js#L75-85

Which will trigger the callback if the the target event name has ever
been triggered. This is helpful when doing things like coordinating
startup between disjoint modules.

However, I'm not sure once or ensure type features really belong in
the core of node. They are easy enough to add if you need them right
now.

> --
> You received this message because you are subscribed to the Google Groups "nodejs" group.
> To post to this group, send email to nod...@googlegroups.com.
> To unsubscribe from this group, send email to nodejs+un...@googlegroups.com.
> For more options, visit this group at http://groups.google.com/group/nodejs?hl=en.
>
>

Micheil Smith

unread,
Oct 12, 2010, 6:08:43 PM10/12/10
to nod...@googlegroups.com
This looks good, although I think it has a bad scoping issue.

The context of this inside g is g, iirc. I think it should probably
be self in that case not this. Something else that would be
good to see is support for thisArg.

@ryah: thoughts on supporting a thisArg?

Yours,
Micheil Smith
--
BrandedCode.com

Isaac Schlueter

unread,
Oct 12, 2010, 7:21:12 PM10/12/10
to nod...@googlegroups.com
On Tue, Oct 12, 2010 at 15:08, Micheil Smith <mic...@brandedcode.com> wrote:
> This looks good, although I think it has a bad scoping issue.
>
> The context of this inside g is g, iirc. I think it should probably
> be self in that case not this. Something else that would be
> good to see is support for thisArg.

Nope, it's fine, though a bit excessive.

Event listeners are by default called in the this-context of the
emitter, so the "self" variable shouldn't be necessary.

--i

r...@tinyclouds.org

unread,
Oct 13, 2010, 6:10:13 AM10/13/10
to nod...@googlegroups.com
On Tue, Oct 12, 2010 at 2:00 PM, Peteris Krumins
<peteris...@gmail.com> wrote:
> I added .once to EventEmitter, it works just like .on, except executes
> the callback just once. It's really useful when you need to do
> something just once. The name also looks good to me too, just two
> chars longer than .on.
>

Sure, I'll take it. Can you provide it as an attachment?

Peteris Krumins

unread,
Oct 13, 2010, 1:05:24 PM10/13/10
to nodejs


On Oct 13, 1:10 pm, r...@tinyclouds.org wrote:
> On Tue, Oct 12, 2010 at 2:00 PM, Peteris Krumins
>
> <peteris.krum...@gmail.com> wrote:
> > I added .once to EventEmitter, it works just like .on, except executes
> > the callback just once. It's really useful when you need to do
> > something just once. The name also looks good to me too, just two
> > chars longer than .on.
>
> Sure, I'll take it. Can you provide it as an attachment?

On Oct 13, 1:10 pm, r...@tinyclouds.org wrote:
> On Tue, Oct 12, 2010 at 2:00 PM, Peteris Krumins
>
> <peteris.krum...@gmail.com> wrote:
> > I added .once to EventEmitter, it works just like .on, except executes
> > the callback just once. It's really useful when you need to do
> > something just once. The name also looks good to me too, just two
> > chars longer than .on.
>
> Sure, I'll take it. Can you provide it as an attachment?

Some trouble, can't attach via google groups. I put it on my website
for download instead:
http://catonmat.net/ftp/once.patch

Bah, should just have done it via github. Sorry.


P.Krumins

Ryan Gahl

unread,
Oct 13, 2010, 1:16:09 PM10/13/10
to nod...@googlegroups.com
Hmm.

I remember my .once patch being rejected. Times are a'changin' :)


Does this mean you might be ready for the .suppress API? 


Isaac Schlueter

unread,
Oct 13, 2010, 1:35:36 PM10/13/10
to nod...@googlegroups.com
Actually, I was in favor of .once, iirc. It was the .suppress rider
that I objected to, on the basis of the fact that it would add weight
to a very hot code path.

--i

Ryan Gahl

unread,
Oct 13, 2010, 1:38:34 PM10/13/10
to nod...@googlegroups.com
Yeah I know :)

Just stirring the pot. 

.once is a good add. I'll keep using my AOP version of events.js to get the extras. That, and keep dreaming of the day I get my name on the contrib list :)

Sami Samhuri

unread,
Oct 13, 2010, 1:48:06 PM10/13/10
to nodejs
Hi Peteris,

On Oct 13, 10:05 am, Peteris Krumins <peteris.krum...@gmail.com>
wrote:
>
> Some trouble, can't attach via google groups. I put it on my website
> for download instead:http://catonmat.net/ftp/once.patch

Groups doesn't have any UI for attachements but it's a regular mailing
list so you can adjust your subscription settings to send you mail and
then reply or otherwise send mail to nod...@googlegroups.com (and
nodej...@googlegroups.com).

-s

r...@tinyclouds.org

unread,
Oct 16, 2010, 11:44:01 PM10/16/10
to nod...@googlegroups.com
> Some trouble, can't attach via google groups. I put it on my website
> for download instead:
> http://catonmat.net/ftp/once.patch
>
> Bah, should just have done it via github. Sorry.
>

Thanks. Landed in a6ee3bac85c84c1a24c1a2aa621f77ba5d1c0bb9.

Reply all
Reply to author
Forward
0 new messages