busboy icon indicating copy to clipboard operation
busboy copied to clipboard

[feature] asyncIterator

Open jimmywarting opened this issue 5 years ago • 0 comments

working with streams in this manner feels a bit awkward, especially when ppl turns more to the way of using async/await

Symbol.asyncIterator is grate for this manner. Combining it with some of browser FormData iterator + File IDL stuff would make you feel right at home with familiar api's I would propose something in the line of this:

const asyncIterable = req // (streams have asyncIterator now days)
const busBoy = new Busboy({ headers: req.headers, body: asyncIterable })

for await (const [key, value, ...extra] of busBoy) {
  if (typeof value === 'string') {
    // plain key/value strings
  } else {
    // got a file/blob like object
    console.log(value.name) // name
    console.log(value.type) // mimetype
    console.log(value.size) // unknown, can't figure out due to streaming issue (could perhaps be updated when it finish)
    console.log(await value.text()) // promise that would resolve to string
    console.log(await value.arrayBuffer())  // promise that would resolve to arraybuffer
    console.log(value.stream())  // returns a whatwg readable stream (require node v18?)
    console.log(value.nodeStream())  // returns a node readable stream
    console.log(value.iterable)  // returns the current iterator for this current file
    console.log(await value.iterable.toArray())  // promise that would resolve with all chunks as Uint8Array[]
    console.log(value.headers) // 2D array that could be passed to `new Headers(x)`
  }
}

The iterable parser reads all the chunks

  1. If the parser encounter a text field it should yield the key/value and pause the parsing
  2. if it's a file yield a file like IDL object and pause the parsing 2.1. if the user calls text() or arrayBuffer() consume the rest of the parsing for the current field and then yield the value. calling this method again should result in an error. since they can only be read once 2.2 if the user calls .stream() create a readable stream from using Readable.from(iterator)
  3. the user calls busboy[Symbol.asynciterator]().next() (or just loop on to the next one) if the developer don't consume previous text, arrayBuffer or stream drain everything and make the text, arraybuffer, stream methods unusable and move on to the next field and start over

This is what i would like to see in a multipart/formdata parser it's maybe a bit out of the scope of how things are built with busboy and perhaps to much to ask for - so i don't have high hopes of this landing into busboy (also due to compatibility issues, if any)

jimmywarting avatar Jun 16 '20 19:06 jimmywarting