简体   繁体   中英

In Javascript, how do I read multiple stream chunks from one API request using fetch()?

In my Node/Express backend, I have a long (10 - 15sec) API call that sets up a user's account.

The call is triggered from my front-end by doing a simple fetch('my/api/url') GET request.

I'd like to be able to send messages to the frontend/my user about the status of the request. ("Setting up your profile", "Downloading your contacts", "Processing data" etc etc etc)

In my Express route, I'm (attempting) sending data via:

exports.setupAccount = async () => {
   res.write("Getting contacts");

   // A bunch of code and async awaits
   // and when it's done...
   res.write(`Retrieved ${contacts.length} contacts!`);
}

I'm trying to comprehend the Mozilla Fetch() API at the moment and am not even sure if I'm looking in the right place.

In my frontend (just vanilla JS for now) I'm doing:

fetch('/my/setup/api')
.then(response => {
  const reader = response.body.getReader();
  reader.read().then(async ({ done, value }) => {
    console.log("VALUE", value); // <== This returns a Uint8Array
    var str = String.fromCharCode.apply(null, value);
    console.log("Message from API:", str);
  })
})

This works, but only gives me the first res.write() sent from the server, and doesn't log out subsequent writes. How do I read multiple stream chunks using this fetch / getReader() method?

Found an answer that works with vanilla JS, using a while loop with await :

fetch('/my/api')
.then(async response => {
  const reader = response.body.getReader();

  while(true) {
    const {done, value} = await reader.read();
    // If it's done, there will be no value
    if (done) {
      console.log("Done!");
      break;
    }
    // value is Uint8Array of the chunk bytes
    var str = String.fromCharCode.apply(null, value);
    console.log(str)

  }
})

Using response.text() will read the stream to completion. We can also use the Response object to retrieve other formats like blobs ( response.blob() ) or json ( response.json() ) as well.

fetch('/my/setup/api')
.then(response => response.text())
.then(text => console.log("Message from API:", text))

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM