简体   繁体   中英

javascript, nodejs await promised array

I have a problem with promised array: I'm calling inside my switch a function which is loading an array from API Example:

let sorted = []
let limit = 10
async function loadPage(slcLimit) {
    let i
    let filter = document.getElementById("show-filter").value

    if (sorted.length == 0) {
        switch (filter) {
            case "1":
                let realWoolPromiseAsc = await Promise.resolve(realWool(pagingPouches))
                    .then((realWoolArr) => {
                        sorted = realWoolArr.sort((a, b) => parseFloat(a.realWool) - parseFloat(b.realWool));
                        return sorted
                    })
                break;
            case "2":
                let realWoolPromiseDesc = await Promise.resolve(realWool(pagingPouches))
                    .then((realWoolArr) => {
                        sorted = realWoolArr.sort((a, b) => parseFloat(b.realWool) - parseFloat(a.realWool));
                        return sorted
                    })
                break;
        }
    }


        for (i = startingLimit; i < (startingLimit + limit); i++) {
            console.log(sorted[i].ID + " - " + sorted[i].price)
        }
}


Real wool function

window.realWool = async function realWool(pouchArr) {
    let divider = 1000000000000000000n;
    let realWoolArray = []
    pouchArr.forEach(async pouch => {
        let availAmount = await pouchContract.amountAvailable(pouch.pouchID)
        availAmount = Number(BigInt(availAmount.toString()) * 100n / divider) / 100
        availAmount = Math.floor(availAmount * 100) / 100
        let rWool = pouch.pouchWool - availAmount
        realWoolArray.push({pouchID: pouch.pouchID, realWool: rWool, pouchTime: pouch.pouchTime})
        //document.getElementById("lockedText" + pouch.pouchID).innerHTML = "Real WOOL: <span class='black'>" + rWool + "</span>"
    });
    return realWoolArray
}

I need to use the sorting array inside my for loop but I'm getting undefined. I understand I need to use await or a then block I just have no clue how to use that.

Thank you!

I've used a timeout , but it is not optimal since sometimes the function just return an array of 5 objects and sometimes a hundreds of objects (depends on filters)



setTimeout(() => {
        for (i = startingLimit; i < (startingLimit + limit); i++) {
            console.log(sorted[i].ID + " - " + sorted[i].price)
        }
}, 5000);


You need to return from the then block.

And spell length correctly.

You do not need to set the module scoped sorting in the then block either.

     let promisedArray = await Promise.resolve(myFunction())
     .then((realArray) => {
         sorting = realArray.sort((a, b) => parseFloat(a.price) - parseFloat(b.price));
        
         return sorting // <-- return to awaited value
      })

      for (let i = 0; i < promisedArray.length; i++) { <-- check spelling
         console.log(promisedArray[i]) //returns the value I need
        }

You do not need await Promise.resolve either, just await realWool .

Your problem is here: pouchArr.forEach(async pouch => {...}) this is a fire and forget situation. forEach will start all the tasks at once and then as soon as all have started, forEach is done and your code goes to the next command return realWoolArray before even the first entry has been added.

Then in loadPage your sort will sort a (currently) empty array, ... and when all your synchronous code is done, and the Promises start to resolve, your code pushes the items all the way into the sort array.

window.realWool = async function realWool(pouchArr) {
    const divider = 1000000000000000000n;
    return Promise.all(
      pouchArr.map(async (pouch) => {
        let availAmount = await pouchContract.amountAvailable(pouch.pouchID)
        availAmount = Number(BigInt(availAmount.toString()) * 100n / divider) / 100;

        return {
          pouchID: pouch.pouchID, 
          realWool: pouch.pouchWool - availAmount, 
          pouchTime: pouch.pouchTime
        }
      })
    );
}

The array sorted that you use in the loadPage function is a global variable, which means that all invocations of loadPage (I assume that each incoming request causes one invocation) will access the same array concurrently. This cannot lead to correct (or even predictable) results.

Put the let sorted = [] inside the function body to make it local. And the function must return something, for example return realWoolPromiseAsc .

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