What is the best way to extract and retrieve the most recent data from an XmlHttpRequest?

Currently, I am using a web service that returns an SseEmitter to program a loading bar. The method to receive it looks like this:

static async synchronize(component: Vue) {
    let xhr = new XMLHttpRequest();
    xhr.open('PATCH', 'myUrl.com');
    xhr.responseType = "text"
    xhr.setRequestHeader('Authorization', 'mySessionToken')
    xhr.setRequestHeader("Content-Type", "text/event-stream")
    xhr.onload = function () {
        if (this.status >= 200 && this.status < 300) {
            resolve(xhr.response)
        } else {
                reject({status: this.status, statusText: xhr.statusText})
        }
    }
    xhr.onerror = function () {reject({status: this.status, statusText: xhr.statusText})}
    xhr.onreadystatechange = function() {if (xhr.readyState == XMLHttpRequest.DONE) { alert(xhr.responseText) }}
    xhr.onprogress = function(onEvent) {
    console.log(xhr.response)
    }
    xhr.send()  
}

Everything is working fine so far, but there is one issue: the xhr.response data is returned as a string like this:

data:"{ hello: '1' }"
data:"{ hello: '2' }"
data:"{ hello: '3' }"
...
data:"{ hello: '100' }"

While this seems okay, the problem arises when each emitted event returns the entire state history, causing the response to grow with each value:

https://i.sstatic.net/FCcyu.png

In essence, is there a way to only retrieve the last value from the response? Using Json.parse() is resulting in errors, possibly due to the response not being formatted as JSON.

I could provide some code from the web service where the SseEmitter originates, but I believe it may not be necessary to address this issue. Thank you for any assistance!

Answer №1

What is the reason behind opting for XMLHttpRequest over EventSource for consuming SSE?

Regardless, if there is a valid justification, additional steps need to be taken.

Start by creating a new function to receive the most recent data block in the form of a JavaScript object, not a string:

function onData(d){
console.log(d)
}

Next, the concept is to keep track of the processed data and extract only the new portion:

let lastLen = 0

xhr.onprogress = function(onEvent) {
  const s = xhr.response.slice(lastLen+5)
  lastLen = xhr.response.length
  onData(JSON.parse(s))
}

If we used xhr.response.slice(lastLen), we would only retrieve the last "data: {...}" block (potentially with extra whitespaces included), hence the addition of +5 to skip the "data:" part.

This method is somewhat delicate. If there are leading whitespaces, the +5 calculation might be incorrect. Additionally, there could be scenarios where multiple "data: {...}" blocks arrive concurrently. In such instances, consider something like:

const parts = xhr.response.slice(lastLen).split("\n\n")
and process each segment within parts.

For a more comprehensive approach, delve into the EventSource standard or explore the code of existing polyfill libraries. Alternatively, utilize one of these polyfill libraries for a smoother implementation ;-)

Answer №2

To convert the JSON string into an object, parsing is necessary

const objectData = JSON.parse(xhr.response.replace("data:", "")) // { hello: 'xx' }

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

Looking to manipulate the form submit data before it is submitted using the standard submit event and jQuery? Read on to learn how to remove, enhance, or change

Is there a way to extract data from a form like the one below? <form action="/search/search" data-remote="true" data-type="json" id="search_form" method="get"> <div class="input-group"> <span class="input-group-addon"> <i ...

The cropper fails to load within the image element inside a modal pop-up

Utilizing fengyuanchen's cropper library, I am cropping an uploaded image and then submitting it to a form. <div id="change-dp" uk-modal> <div class="uk-modal-dialog uk-modal-body"> <button class="uk ...

When invoking the function, the original state remains unaffected within a separate function

Whenever I click on an 'item', it should establish an initial value for me to use in a comparison within another function that involves the mousemove event. However, when the mousemove function is triggered, the initial state remains at 0. imp ...

Typescript and Apollo Client return types intertwined

My goal is to create a simple function within a class that generates an Apollo Client. Below is the code I have implemented: import appConfig from 'config/app-config'; import { ApolloClient, InMemoryCache, createHttpLink } from '@apollo/clie ...

example of reusing vue js component multiple times on a single page

Within my components, I am making an axios call. I have defined two of them with props that provide the URI for the axios call. export default { name: "CardData", props :['uri','suffixe' ,'label'], data : function (){ r ...

Can a FilePicker be Cleared Automatically through Code?

Currently, I am implementing an‘<input type="file" . . .’ to select files individually and then attach them to a table located right under the file picker. This functionality is quite similar to using the attachment button on a SharePoint form’s r ...

There was a serious issue: The mark-compacts were not working effectively near the heap limit, resulting in allocation failure - the JavaScript heap ran out of memory during the

I recently set up a t2.micro server on AWS and encountered an issue when running our application with the command "sudo npm start". The error message I received was: "FATAL ERROR: Ineffective mark-compacts near heap limit Allocation failed - JavaScript he ...

The specified file path '.../node_modules/@nomicfoundation/hardhat-core/src' could not be located

I have successfully set up a TypeScript hardhat project, but I encountered an issue in /***/node_modules/@nomicfoundation/hardhat-chai-matchers/src/tsconfig.json: { "extends": "../../../config/typescript/tsconfig.json", "compil ...

Utilizing an observer to encapsulate a custom React hook- a comprehensive guide

As part of my project, I have developed a unique custom react hook that relies on observable state from the store for its dependencies within useEffect: Here is an example of my custom hook: const useFoo = (() => { const { count } = store; useEff ...

What is the best way to implement CSS properties on Material UI components?

I've recently started exploring Material UI, but I'm having trouble understanding how the spacing properties function. I'm trying to utilize the "spacing" feature for various elements, but it appears that it only works for "Box" components a ...

What is the best way to specify the stream responseType for my client?

Is there a way to download a file from my express js app using AJAX instead of server-side handling? const response = await Axios({ method: 'GET', url: url, responseType: 'stream' }) Instead of piping the data directly to ...

Placing an image onto a THREE.js plane

Whenever I attempt to place a .png image on my plane, it simply vanishes. Could it be that THREE.js isn't compatible with Vue.js? Is there another 3D library that supports Vue.js? I'm also interested in adding an SVG, but I haven't quite f ...

The Android webview encountered an error: XMLHttpRequest failed to load because the specified Origin <url> is not permitted by Access-Control-Allow-Origin restrictions

I have developed an application that loads an entire website in an Android WebView. The native code in the Android project communicates with the webpage using the Android Jockey Library, and vice versa. Everything is working smoothly except for one instan ...

Encountering a TypeScript error within the queryFn while implementing Supabase authentication alongside React Toolkit Query

I've been attempting to integrate Supabase authentication with React Toolkit Query but encountering an issue with the utilization of the queryFn. Here is the code snippet that employs supabase.auth.signUp to register a user using email/password. You ...

Specify the second parameter as a generic class that corresponds to the first parameter of the function

Given the example below, the second parameter of the fn function requires a class with a static attribute controle and an instance attribute controle, both of type number. interface Base { controle: number new(...args: any[]): { controle: n ...

Tips for converting Javascript require to Typescript import using the const keyword

Recently, I've been attempting to import faktory_worker_node from github.com/jbielick/faktory_worker. The README provides the following instructions: const faktory = require('faktory-worker'); faktory.register('ResizeImage', asyn ...

What is the best method for ensuring image orientation is displayed correctly?

When utilizing multer node and express for uploading images to my application, I've noticed that some of the images appear rotated 90 degrees once they reach the client side. What could be causing this issue, and how can I resolve it? Just to clarif ...

Position the <a> to the right side of the div

Is there a way to right-align the <a> element, which contains a Button with the text Push Me, within the <div> (<Paper>)? https://codesandbox.io/s/eager-noyce-j356qe This scenario is found in the demo.tsx file. Keep in mind that using ...

Incorporate a gradient into a Vuetify v-card background image

<v-card :img="require('@/core/assets/homeBg.png')" > </v-card> Although the image is currently displaying properly, I am interested in finding a way to add a gradient effect to it. (Specifically, I aim to darken the imag ...

the language of regular expressions expressed in strings

As a beginner in Javascript and regular expressions, I found myself stuck on how to create a route that matches all URLs starting with /user/.... Initially, I thought of using app.get(/user/, function(req, res){ /*stuff*/}); However, curiosity led me to ...