Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

unexpected behavior from ofetch.raw and onResponse #405

Closed
1 task done
o-az opened this issue Jun 17, 2024 · 2 comments
Closed
1 task done

unexpected behavior from ofetch.raw and onResponse #405

o-az opened this issue Jun 17, 2024 · 2 comments
Labels
documentation Improvements or additions to documentation

Comments

@o-az
Copy link

o-az commented Jun 17, 2024

Describe the change

I'm trying to track the response progress, something which I do all the time when using the native Fetch API. However I'm encountering unexpected behavior with ofetch:

import { ofetch } from "ofetch"

// native fetch: logs progress
fetch("http://localhost:3000")
  .then(response =>
    onResponse({
      response,
      onProgress: progress => console.info(progress)
    })
  )
  .catch(console.error)

// Does not log progress
ofetch
  .raw("http://localhost:3000")
  .then(response =>
    onResponse({
      response, // also tried passing `response._data` for body
      onProgress: progress => console.info(progress)
    })
  )
  .catch(console.error)

// Does not log progress
ofetch("http://localhost:3000")
  .then(response =>
    onResponse({
      response,
      onProgress: progress => console.info(progress)
    })
  )
  .catch(console.error)

// Does not log progress
ofetch("http://localhost:3000", {
  onResponse: async context =>
    onResponse({
      response: context.response,
      onProgress: async progress => console.info(progress)
    })
}).catch(console.error)

type MaybePromise<TValue> = TValue | Promise<TValue>

async function onResponse({
  response,
  onProgress
}: { response: Response; onProgress: (progress: number) => MaybePromise<void> }) {
  console.info(`Response status: ${response.status}`)

  const reader = response.body?.getReader()
  if (!reader) return

  const contentLengthHeader = response.headers.get("content-length")
  const length = contentLengthHeader ? +Number.parseInt(contentLengthHeader) : undefined

  let receivedLength = 0
  let chunks: Array<Uint8Array> = []

  while (true) {
    console.info("Reading...")

    const read = await reader?.read()
    if (read?.done || !read?.value) break

    receivedLength += read.value.length
    chunks.push(read.value)

    // Calculate progress as a percentage if length is defined
    const progress = length ? (receivedLength / length) * 100 : receivedLength
    await onProgress(progress)

    console.info(`Received ${receivedLength} of ${length} bytes`)
  }
}

testing server:

import http from "node:http"

http
  .createServer(async (req, res) => {
    res.writeHead(200, { "Content-Type": "text/plain", "Content-Length": "110" })
    const chunks = ["Hello ", "World", "\n"]
    for (const chunk of chunks) {
      res.write(chunk)
      await new Promise(resolve => setTimeout(resolve, 1_000)) // Simulate delay between chunks
    }
    res.end()
  })
  .listen(3_000, "localhost", () => console.log("Server running at http://localhost:3000/"))

URLs

No response

Additional information

  • Would you be willing to help?
@o-az o-az added the documentation Improvements or additions to documentation label Jun 17, 2024
@o-az o-az changed the title unexpected behavior from ofetch.raw and onResponse unexpected behavior from ofetch.raw and onResponse Jun 17, 2024
@Aareksio
Copy link

Aareksio commented Jun 17, 2024

This is by design.


ofetch.raw is not the equivalent of native fetch (you can access it using ofetch.native). It only gives you the whole response object after the request has been completed, instead of only the data (.json() / .text() return value). I believe you could set the responseType parameter to 'stream' and it may skip awaiting data, see source. However, if you do so, you'll be responsible for parsing the response (eg. r.text()) yourself.

Also see: #45

@pi0
Copy link
Member

pi0 commented Aug 28, 2024

Let's track progress support via #45

@pi0 pi0 closed this as not planned Won't fix, can't repro, duplicate, stale Aug 28, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
documentation Improvements or additions to documentation
Projects
None yet
Development

No branches or pull requests

3 participants