Skip to content

Add context argument to emitter #15763

Closed
Closed
@hueniverse

Description

@hueniverse

As part of the hapi v17 work, I removed every closure from the hot path. This provided significant performance improvements. All these closures came from handlers passed to node EventEmitters (specifically from req and res object). In order to do that, I had to hang my own property on the emitter object. For example:

const handler = function (err) {
    this._context.log(err);
};

// Inside some prototype methods:

req._context= this;
req.on('error', handler);

This works and can be improved by using symbols, but it's still messy. It also means adding multiple context properties per handler because they might need different context data. Instead, I would like to be able to do something as simple as:

const handler = function (err, context) {
    context.log(err);
};

// Inside some prototype methods:

req.on('error', handler, this);

The idea is to pass a third optional argument to on() and then append that argument to the end of the emit arguments list. We already store listeners as objects with properties. When this feature is not used, it means two additional if statements: once to check if a third argument was provided and another to check if one is present and needs to be appended. If no third argument is provided, these two extra if statements should not have any noticeable impact on performance.

However, since 99% of the time, emitter handlers require the creation of a callback closure, this should make applications using it much faster overall. Potentially, this can be used internally by node as well.

There is already a pattern for this in setTimeout(). Most new JS features with callbacks now accept some kind of extra binding argument. Because we already bind the handler to the emitter, we cannot use this pattern.

I'm happy to do the work if the idea is acceptable.

Metadata

Metadata

Assignees

No one assigned

    Labels

    eventsIssues and PRs related to the events subsystem / EventEmitter.feature requestIssues that request new features to be added to Node.js.stalledIssues and PRs that are stalled.

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions