Skip to content

Async iterator patterns #1723

@mafintosh

Description

@mafintosh

Wanted to get feedback on a series of complexities I've been hitting with standard and async iterators. Basically it's hard atm to write functions that uses async iterators to do specific operations. Here is an example:

Return the first item in an iterator

async function peek () {
  for await (const data of createIterator()) {
    return data
  }
  throw new Error('Not found')
}

This results in Invalid loop. Its body allows only one iteration.. Unless someone knows a better pattern the way to write the equivalent in standard friendly syntax is

const ite = createIterator()[Symbol.asyncIterator]()
try {
  const next = await ite.next()
  if (!next.done) return next.value
} finally {
  await ite.return()
}
throw new Error('Not found')

Personally I find the first version much more readable and understandable.

Equivally I've had issues making assertions in tests with async iterators, like "check if this iterator returns any values" as that runs into "data is defined but never used" lints, ie:

async function assertEmpty (t) {
  for await (const data of iterator) {
    t.fail('should be empty')
    return
  }
}

I don't know if there is any ESlint specific rules to async loops to make this easier, but wanted to share to hear if anyone was running into the same kind of issues.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    Status

    No status

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions