Skip to content

Intermittent hang when aborting reading request bodies #766

@achingbrain

Description

@achingbrain

I've noticed that for await..of loops occasionally hang when you return early and you don't read the response body to completion:

async function parse (source) {
  for await (const buf of source) {
    if (... some criteria) {
      // exit early
      return 'some value'
    }
  }
}

const res = fetch('http://...')
const result = await parse(res.body) // this promise *sometimes* never resolves or rejects

res.body here is a PassThrough stream - the workaround is to wrap the async iterator it produces and destroy the stream when the return method is called, but it only seems to be necessary if the writable side has ended:

const res = fetch('http://...')
const iter = res.body[Symbol.asyncIterator]()

const wrapped = {
  next: iter.next.bind(iter),
  return: () => {
    if (res.body.writableEnded) {
      res.body.destroy()
    }

    return iter.return()
  }
}

const result = await parse(wrapped) // now always resolves

Can this be handled by node-fetch or is this a problem with node itself?

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions