javascript: Make sure to update the DOM only after the result has been successfully obtained

I have access to an API endpoint that returns server details (). There are also server-specific endpoints, for example () where I have to call each one for every server ID obtained from the "serverDetails" endpoint.

My current approach involves looping over the results array retrieved from the "serverDetails" endpoint and calling each endpoint in a synchronous manner to fetch the IP address.

Here's a snippet of my loop:

 for (const [index, item] of data.entries()) {
    const res = await fetch(
      `https://dnscheck.io/api/query/?id=${item.id}&type=${query.type}&hostname=${query.host}`
    );
    const result = await res.json();

    renderResult(result, item, index);
  }

The above code renders the results one after another in the DOM. However, I want to update the DOM as soon as each result is ready. How can I achieve this?

If you have any suggestions or solutions, please let me know.

Answer №1

Avoid using await since it can cause the for loop to hang and disrupt the order of outcomes. Instead, opt for utilizing .then().

for (const [index, item] of information.entries()) {
  fetch(
      `https://websitecheck.com/api/data/?id=${item.id}&type=${query.type}&host=${query.host}`
    ).then(response => response.json())
    .then(outcome => displayOutcome(outcome, item, index));
}

Answer №2

To run multiple tasks simultaneously, you can utilize the map method on an array and integrate fetch within it. Tracking when all tasks have completed is achievable by employing Promise.all to monitor the overall outcome:

await Promise.all(
    data.entries().map(async (index, item) => {
        const res = await fetch(
            `https://dnscheck.io/api/query/?id=${item.id}&type=${query.type}&hostname=${query.host}`
        );
        // Verify the response using `res.ok` at this point
        const result = await res.json();
        renderResult(result, item, index);
    )
);

It is important to note that Promise.all will immediately reject its promise if any of the input promises encounters a rejection. If you need to differentiate between successes and failures, consider using allSettled instead:

const results = await Promise.allSettled(
    data.entries().map(async (index, item) => {
        const res = await fetch(
            `https://dnscheck.io/api/query/?id=${item.id}&type=${query.type}&hostname=${query.host}`
        );
        // Check the response status with `res.ok` here
        const result = await res.json();
        renderResult(result, item, index);
    )
);
// Utilize `results`, which is an array of objects representing success or failure
// {status: "fulfilled", value: <the fulfillment value>}
// or
// {status: "rejected", reason: <the rejection reason>}

In reference to my observation "Verify the response using res.ok at this point": This cautionary advice pertains to an inherent issue in the fetch API where it does not reject promises for HTTP errors like a 404. Instead, it treats such cases as fulfilled promises. You can find more insights on this topic in my article found here. A recommended approach is to implement wrapper functions for handling these situations, as shown below:

function fetchJSON(...args) {
    return fetch(...args)
    .then(response => {
        if (!response.ok) {
            throw new Error(`HTTP error ${response.status}`); // Or a more specific error type
        }
        return response.json();
    });
}

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

Is there a way to determine if a browser supports the offline event?

I attempted to implement the code from this Stack Overflow question: How can I check for support of the `focusin` event? However, in Chromium, the method hasEvent('offline') returns false even though it supports the `offline` event. Does anyone ...

Left-hand navigation panel that complements entire screen

Web Design .sidenav { height: 100%; position: relative; overflow-y: scroll; background: #000000; width: 15%; } Ensuring the menu covers the full screen correctly by setting its height to 100% is effective, but it may appear awkward wh ...

Struggling with updating state using splice method within an onClick event in React Hooks

CODE DEMO I'm facing an issue with my code snippet where it appears fine when I console.log it, but fails to set the state. The goal is to delete a box by using splice when clicked, however, something seems to be preventing it from working properly. ...

Associate the URL with the object to retrieve the corresponding object

https://i.sstatic.net/cj5N4.png When iterating through this array, I currently loop through it in the following manner: {props.choosenMovie.characters.map((characters) => ( <p>{characters}</p> /* This displays the URL of course */ ))} ...

Select2 Dropdown Options Do Not Update Background Color

I am currently implementing the Select2 Input CSS/jQuery framework from to assist me in handling multi-select boxes. However, I am facing difficulty in changing the background color of the results when the select box is clicked. To provide a better under ...

In order to ensure proper coverage for phones, tablets, and standard screens across various widths, it is essential to implement the

As I delve into my project focused on responsive design and media queries, I have been studying resources like Aaron Gustavson's book, Adaptive Web Design, and Ben Frain's Responsive Web Design with HTML5 and CSS3, along with various online sourc ...

JS method for gradually reducing the opacity of various div elements

I currently have two divs with background images styled using CSS. My goal is to create a loop that fades them in and out continuously. While attempting to achieve this effect, I encountered some issues and the following code snippet doesn't seem to ...

Encountering errors during the installation of packages using npm

Can someone please assist me with fixing these errors? I am a beginner in the world of web development and encountered this issue while working with react.js and setting up lite-server. Any guidance on how to resolve it would be greatly appreciated. ...

What is the best way to enhance the appearance of labels on my Google Maps using the Google Maps API?

I've created a map that pulls data points from a json file. I've successfully displayed an image as a marker and added a label, but I'm struggling with styling the label. How can I add style to the label without affecting the map or coordina ...

How to enhance form validations in Angular 2 using ngModelGroup

I am currently utilizing the ngModelGroup directive to consolidate multiple form inputs together. Upon reviewing the documentation (https://angular.io/docs/ts/latest/api/forms/index/NgModelGroup-directive.html), I came across the validators: any[] propert ...

Experiencing disconnection from SQL server while utilizing the Express.js API

Im currently working on an API that retrieves data from one database and posts it to another database, both located on the same server. However, I am facing issues with the connections. Initially, everything works fine when I run the app for the first time ...

Is there a way to eliminate this pesky margin?

please check out this: https://jsfiddle.net/desytec/73qdtejg/1/#&togetherjs=w3lvLQi0v6 This displays the following table definition: <table id="semana" class="table table-striped dt-responsive table-bordered display ...

Using Jquery to retrieve the selected value from a dropdown menu

Here is the HTML code I am using for a dropdown list: <select id="dd"> <option>Select ReportType</option> <option value="1">Blocked Details</option> <option value="2">Supervisor Input</option> </ ...

Avoid mutating the prop directly and instead, utilize a data or computed property that is based on the value of the prop. The prop that is being mutated in this case is

Help me understand this issue that Vue is displaying, I am not sure what is going on. This is my progress element: <el-progress :percentage="percentCompleted" v-show="uploadingVideo"></el-progress> data() { return{ percentCompleted: 0 ...

I'm curious about the distinction between React's one-way data binding and Angular's two-way data binding. Can someone please clarify the key differences

My understanding of these concepts is a bit hazy. If I were to develop the same ToDo application using AngularJS and ReactJS, what exactly distinguishes React ToDo's use of one-way data binding from AngularJS's two-way data binding? From what I ...

Securing client-side code with AngularJS for enhanced security

It's a known fact that once browsers have downloaded frontend files, there's no way to hide code from the client. However, I've heard that clients can debug JavaScript code, add breakpoints, skip code lines (especially security checks), and ...

Upgrade an existing create-react-app project ejected with react-app-rewired from webpack 4 to webpack 5

I am currently working on updating an old React application that was initially created using create-react-app and later ejected with react-app-rewired. The task at hand is to upgrade all deprecated dependencies. So far, I have successfully updated react-sc ...

Form featuring a mandatory checkbox that must be selected in order to proceed; failure to do so will result in an

So here’s the situation: I have a form with a checkbox for agreeing to the terms of service, and I want to make sure it is checked before proceeding with the donation process. I only have the HTML code and no idea how to implement this functionality. Ide ...

Error: The datatable is requesting a parameter that is not recognized, specifically looking for parameter '4' in row

I encountered an error message while attempting to utilize a data table with the jQuery DataTables library. The system raised an issue stating 'Requested unknown parameter '4' for row 0.' <div class="container"> <%= render ...

Arranging HTML components in Vue.js using v-for loop

Recently, I started using vue.js and I have a requirement where I need to display an HTML structure based on API data. The structure should look like this: <div class="row"> <div><p>text1</p><img src="{{imgurl1}}" /></di ...