Skip to content

stream: How to destroy and stop Readable? #29856

Open
@ronag

Description

I ran into this today:

const { Readable } = require('stream');

const someOtherResource = {
  doStuff () {
    if (this.destroyed) {
      throw new Error('destroyed!')
    }
  },
  destroy () {
    this.destroyed = true
  }
}

const r = new Readable({})

r.on('data', () => {
  someOtherResource.doStuff()
})
someOtherResource.destroy()
r.push('asd')
r.destroy() // or r.destroy(new Error('kaboom'))
r.read()

This will crash with destroyed! since read() will emit already buffered 'data' even though the stream is destroyed.

I can fix my above example by replacing r.destroy() with:

function destroy (r) {
  r.removeAllListeners('data')
  r.destroy()
}

I find this a bit unfortunate.

Questions:

  • Is this expected behaviour?
  • Can we fix it without breaking the ecosystem?
  • If no, can we provide another method to Readable that makes it possible to fully destroy and silence a readable?

In order to fix this in readable we would have to check for destroyed and return early inside Readable.read().

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Assignees

No one assigned

    Labels

    streamIssues and PRs related to the stream subsystem.

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions