Counting and Arranging Numerous Commitments in the World of Javascript

I’m faced with a challenging scenario that’s got me puzzled:
-I’ve got an array of 10 objects, each with two properties: IDNum and imageURL.
-Only 3 of these objects actually have their imageURL property set (at index positions [0, 4, 9]), and now I need to retrieve their images.
-I swiftly create another array named imageURLsArray containing these 3 URLs, and then use .map to attach a Promise to each one:

// (there’s some THREE.js code but focus on the issue of enumerating Promises in Javascript)

function getTextures(theImageURLsArray) {
    const loader = new THREE.TextureLoader(); // This lets you load images from remote URLs using THREE.js

    return theImageURLsArray.map((currentURL, index) => {
       console.log("  Inside '.map', currentURL # ", index, " is: ", currentURL);
  
       return new Promise(function(resolve, reject) {
           console.log(" >>Inside 'new Promise' — will now call loader.load() function!");
    
           loader.load(currentURL, function(theReturnedLoadedTexture) {
              console.log("\n  RETURNED from 'loader.load()', index#", index, ", with currentURL = ", currentURL);
              console.log("  Will now call 'resolve()' with this Texture!");
              resolve(theReturnedLoadedTexture)
           },

           function(err) { 
             reject(err);
           })
       }) 

     }) 
   }  

To make it all come together, follow these steps:

Promise.all(getTextures(imageURLsArray))
   .then(returnedTexturesArray => {
       console.log("Here are the returned textures:");
       console.log(returnedTexturesArray);
    
       theTexturesArray = returnedTexturesArray;

       // Manually iterate through these textures to check them out:
       for(z = 0; z < theTexturesArray.length; z++) {
         tempTexture = theTexturesArray[z];   
         console.log("tempTexture # ", z, "'s IMAGE property = ", tempTexture.image.currentSrc);
       }
       // Use these Textures to map onto 3D Materials...
    })
  .catch(err => console.error(err))

Everything works flawlessly except for one thing - the order in which the Promises return is not guaranteed. This means they may come back in a different order than they were created in.

This causes a mismatch between the original imageURLsArray and the resulting returnedTexturesArray.

We need to ensure that Image # 4 doesn’t mistakenly end up in Cell # 0 when loading images into something like a grid-Table.

The challenge is maintaining the correct ordering of images even when working with a large scale of up to 1000 objects and corresponding images in an efficient manner.

Answer №1

Initially, it is important to note that Promise.all() guarantees the order of results will match the order of the promises passed into it. Therefore, when you use Promise.all([p1, p2, p3]), the resulting array will maintain the same order regardless of completion sequence. If maintaining this order suffices for your needs, then utilizing the default order is recommended.

Another approach is to include an object with both an ID and an index as parameters in your function. Upon resolving the image, return an object containing the image data along with its corresponding index. This method enables you to identify the index and correctly insert the data into the array.

Alternatively, a more efficient strategy involves leveraging Promise.all() to handle a greater portion of the process. By feeding Promise.all() an array comprising promises or values, you can mix promises for empty image slots and actual image data where applicable. Consequently, the output will consist of an array housing all the image data exclusively.

const objArray = [{idNum: id1}, {idNum: id2, imageUrl: url2}, ...];

function fillTextures(array) {
    return Promise.all(array.map(obj => {
        if (obj.imageUrl && !obj.texture) {
             return getTexture(obj.imageUrl).then(texture => {
                 obj.texture = texture;
                 return obj;
             });
        } else {
             return obj;
        }
    }));
}

function getTexture(imageUrl) {
   return new Promise(function(resolve, reject) {
       loader.load(imageUrl, function(texture) {
          resolve(texture);
       },  function(err) { 
         reject(err);
       });
   })     
}

fillTextures(objArray).then(resultsArray => {
    // updated array with added .texture property for objects with .imageUrl
    console.log(resultsArray);
}).catch(err => {
    console.log(err);
});

This streamlined method processes the entire array, initiating asynchronous operations solely on elements requiring them. By allowing Promise.all() to manage the array's integrity, this approach proves simpler compared to selectively processing elements and reintegrating them into the original array.

Answer №2

It seems like there could be a missing piece here. The results from Promise.all appear to always maintain the same order as the input promise array.

To delve deeper into this topic, check out the following answer: Promise.all: Order of resolved values

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

Conceal a designated column within a material angular data table based on the condition of a variable

In the morning, I have a question about working with data tables and API consumption. I need to hide a specific column in the table based on a variable value obtained during authentication. Can you suggest a method to achieve this? Here is a snippet of my ...

Utilizing JavaScript/AJAX JSON encoding for arrays: Tips for effectively utilizing the received data

I am trying to retrieve all the images from a specific folder on the server using an AJAX call. files = glob('assets/img/daily/*'); // obtain all file names $imageArr; foreach ($files as $file) { $imageArr[] = $file; } $jsonObj = json_encode ...

JavaScript - Placing Image Caption and Details within a Box

<div id="CollectionALL"> <div id="collection1" class="col"> <img id="Img1" class="imageCS"/> <H1 id="Title1"></H1> ...

Removing an item from a table row cannot be completed due to the inability to retrieve the list_body ID necessary for deletion

I have been working on enhancing the delete button function in my table. The id linked to the list_body must be incorporated into the delete function code. I utilized some jquery methods to render the list onto the webpage. //retrieve user list information ...

Sending information to a single component among several

I'm developing a custom DownloadButton component in VueJS that features an animation when clicked and stops animating once the download is complete. The DownloadButton will be utilized within a table where it's replicated multiple times. I intend ...

Display data when clicking on Tailwind

I am currently displaying a sub menu on hover using Tailwind CSS. However, I am wondering how I can achieve the exact same functionality by triggering an onclick event instead of hovering over the menu. Here is a DEMO showcasing the current setup. CODE: ...

Transferring a 3D entity to a new location in Three.js

I am facing an interesting challenge in my project involving two 3D objects: a sphere and a car. My goal is to simulate the movement of the car on the surface of the sphere. The tricky part is that I cannot simply place the car on top of the sphere as if ...

Struggling to send information using Angular $resource?

I've been working on sending data to an API using Angular's $resource. Currently, I can successfully retrieve data from my test server using a GET request or querying. However, I'm having trouble figuring out how to send new data to the serv ...

Creating a "select all" feature in an HTML multiple select box with jQuery - a step-by-step guide

I'm currently working on an HTML form that includes a multiple select box. I am looking to create a "select all" option within the multiple select box so that when a user clicks on that option, all other options in the select box are automatically sel ...

Unable to make a POST request to the application

Creating a basic web page with server.js var path = require("path"); var express = require("express"); var app = express(); var bodyParser = require("body-parser"); app.listen(8000, function() { console.log("server is listening on port 8000"); }) app.us ...

Storing website data for localization purposes on the web platform

I am currently working on a project to develop a website that displays the selected language page upon first visit. The idea is that when a user clicks on a language name, such as French, it will be stored in web/local storage. Then, when the user returns ...

Lost variable during the ajax call

Encountering a peculiar issue while attempting to pass a variable as a parameter to a nested ajax request callback: $('form').on('submit',function(e){ $.ajaxSetup({ header:$('meta[name="_token"]').attr('conte ...

Generate a new entry by analyzing components from a separate array in a single line

I have a list of essential items and I aim to generate a record based on the elements within that list. Each item in the required list will correspond to an empty array in the exist record. Essentially, I am looking to condense the following code into one ...

Button-click scrolling is our featured feature!

One interesting feature on my website is a button (within a div-element) located in the bottom-right corner. I am now looking to enhance this by adding a jQuery function that enables the user to scroll down the page incrementally simply by clicking and hol ...

Unusual issue with jQuery function failing to detect click events

As I delve into my first jQuery function, the primary goal is to assign a form to the function. Upon clicking the submit button, it should perform validation on each :input field within the function. The form is set as the selector for the function: $("f ...

Resolving Meteor collections in the ui-routerIncorporating

My goal is to utilize meteor angular js ui-router resolve to fetch information of a user selected from a user list. $stateProvider .state('userprofile', { url: '/user/:userId', cache: false, template: ' ...

Decipher and refine an array in JavaScript by filtering it

Within our existing codebase, we make use of Newtonsoft.Json.JsonWriter to generate a JavaScript array in the following format: [["1","zxc"],["2","fifa"],["3","fgh"]]. I am curious about whether Newtonsoft.Json offers any functionalities that could assi ...

Determine whether a response is not received within 8 seconds

One of the methods in my Angular component is responsible for returning data Here is a snippet of that method getRecognitionById() { this.loaderService.show(null, true); forkJoin( this.vendorWebApiService.getRecognitionById(this.executiveCh ...

How can I use node-canvas to render three.js on the server-side?

I've been attempting to display images using the official three.js package, three, from npm with the canvas package also from npm. Unfortunately, I haven't had much success so far. I believe it should be doable since node-canvas (https://github. ...

What is the most efficient way to cycle through HTML image elements and display a unique random image for each one?

I'm currently working on coding a simple game that involves guessing the Hearthstone card based on its flavor text. I plan to add a button later to progress in the game, but I haven't implemented that yet. To start, I created 4 image elements an ...