question-mark
Stuck on an issue?

Lightrun Answers was designed to reduce the constant googling that comes with debugging 3rd party libraries. It collects links to all the places you might be looking at while hunting down a tough bug.

And, if you’re still stuck at the end, we’re happy to hop on a call to see how we can help out.

Returning response body as an async-iterable or a readable stream

See original GitHub issue

Apart from normal data types (string, number, object, etc), Deno.Reader is the only other data type that is supported as a response body. It would be good if oak also supported async-iterable/Readable streams as a response body since they can be easily generated and composed using generators.

function getUsers() {
  return knex('users').stream()
}

async function* reports() {
  for await (const user of getUsers()) {
    yield expensiveOperation(user.id)
  }
}

async function* json2csv(iterable) {
  for await (const obj of iterable) {
    yield Object.values(obj).join(',')
  }
}

router.get('/reports', (ctx) => {
  ctx.response.body = json2csv(reports())
})

Issue Analytics

  • State:closed
  • Created 3 years ago
  • Comments:5

github_iconTop GitHub Comments

2reactions
kitsonkcommented, Jan 24, 2021

@ducaale there are a few challenges with the approach… ultimately it needs to be like BufReader in the sense that the reader can be required to span a iterator cycle of some number of reads, depending on the size of the .byteLength of the read buffer passed in.

I have a patch about half done that will fix this and allow the oak response.body to accept async iterables.

0reactions
ducaalecommented, Jan 24, 2021

I have tested the AsyncIterReader class I had in Deno’s http/server and it seems responses are being streamed as I was expecting.

import { serve } from "https://deno.land/std@0.84.0/http/server.ts";

async function* streamData() : AsyncIterator<string> { /* code omitted */ }
class AsyncIterReader implements Deno.Reader { /* code omitted */ }

const server = serve({ port: 8000 });
console.log("http://localhost:8000/");
for await (const req of server) {
  const body = new AsyncIterReader(streamData());
  req.respond({ body });
}
# Notice how each chunk of the response is delayed by 1 second
[1.3479045s] Chunk: b"{\"name\":\"Joshua\"}\n"
[2.3538616s] Chunk: b"{\"name\":\"Rodriguez\"}\n"
[3.3683234s] Chunk: b"{\"name\":\"James\"}\n"
[4.3769208s] Chunk: b"{\"name\":\"Martinez\"}\n"
[5.3870532s] Chunk: b"{\"name\":\"Harry\"}\n"
[6.3943863s] Chunk: b"{\"name\":\"Thomas\"}\n"
[7.4102371s] Chunk: b"{\"name\":\"Davis\"}\n"

Edit: I suspect this line is what preventing from the data to be streamed.

Read more comments on GitHub >

github_iconTop Results From Across the Web

Does the Node.js "request" library support an async-iterable ...
js libraries and I'm trying figure how to use async iteration over an HTTP response stream. My overall goal is to read a...
Read more >
Using readable streams - Web APIs | MDN
The Request.body and Response.body properties are available, which are getters exposing the body contents as a readable stream.
Read more >
Async iteration for fetch response body · Issue #2520 - GitHub
Currently failing with error TS2504: Type 'Body' must have a '[Symbol.asyncIterator]()' method that returns an async iterator.
Read more >
Easier Node.js streams via async iteration - 2ality
At the end, we have several options for handling the async iterable returned by the last generator: We can convert it to a...
Read more >
Async iterators, operators and pull based streams. - Medium
This method must return an asyncIterator (see below). ... Note: the fromReadable function simply converts any Nodejs Readable Stream into an async iterable....
Read more >

github_iconTop Related Medium Post

No results found

github_iconTop Related StackOverflow Question

No results found

github_iconTroubleshoot Live Code

Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start Free

github_iconTop Related Reddit Thread

No results found

github_iconTop Related Hackernoon Post

No results found

github_iconTop Related Tweet

No results found

github_iconTop Related Dev.to Post

No results found

github_iconTop Related Hashnode Post

No results found