Skip to content

Feature request: allow awaiting event, reject on "error" #21339

@dead-claudia

Description

@dead-claudia

Edit: Added errorEvent option to configure error events

99% of my event adaptation of promises end up looking something close to this:

function open(file) {
    return new Promise((resolve, reject) => {
        const stream = fs.createWriteStream(file)

        function ready() {
            stream.removeListener("ready", ready)
            stream.removeListener("error", fail)
            resolve(stream)
        }

        function fail(e) {
            reject(e)
            stream.removeListener("ready", ready)
            stream.removeListener("error", fail)
        }

        stream.on("ready", ready)
        stream.on("error", fail)
    })
}

This is most frequently with streams, but it also occasionally shows up with other things, including with non-core libraries. What I'd prefer to write is something closer to this:

async function open(file) {
    const stream = fs.createWriteStream(file)
    await stream.awaitEvent("ready")
    return stream
}

My proposed API is this:

  • ee.awaitEvent("name", {includeAll = false, errorEvent = "event"} = {}): Return a promise fulfilled with an array of arguments once "name" is emitted, rejected if it's beat by an "error" event. An extra options object is permitted, and it accepts two options: includeAll, which resolves with an array of arguments intead, and errorEvent, which allows configuring what event is considered the "error" event.

The naïve implementation is pretty simple, and looks very similar to above.

EventEmitter.prototype.awaitEvent = function awaitEvent(event, {includeAll, errorEvent = "event"} = {}) {
    return new Promise((resolve, reject) => {
        const success = (...args) => {
            this.removeListener(event, success)
            this.removeListener(errorEvent, fail)
            if (includeAll) resolve(...args)
            else resolve(args[0])
        }

        const fail = e => {
            reject(e)
            this.removeListener(event, success)
            this.removeListener(errorEvent, fail)
        }

        this.on(event, success)
        this.on(errorEvent, fail)
    })
}

Metadata

Metadata

Assignees

No one assigned

    Labels

    duplicateIssues and PRs that are duplicates of other issues or PRs.eventsIssues and PRs related to the events subsystem / EventEmitter.feature requestIssues that request new features to be added to Node.js.

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions