0

I need to iterate over a Map object - to make it realistic - lets say it is a collection of Polygons (Polygons is represented by a collection of coordinates - lat and long). Every item in the Map has a collection of items (coordinates). With every item (coordinate) in the Map (polygon), I need to do some asynch action that return a Promise. After the promise (return a string) collection is being completed - I would like to push it into an array with a preceding word of "POLYGON...". As all of this ends (the iteration over the Map) - I have an array of "Polygons" and their coordinates. Then I would like to do something with this array. The problem is that the Map iteration ended without taking into consideration the promises in it , meaning - the array that should be populated by the promises in the iteration is undefined when the iteration completed. See my code:

//Polygons is the Map object
let polygonsarray : [] = []
let strPolygonArray : string;
for (let [key, value] of this.Polygons.items.entries())
{
    if (value.PolygonItem)
    {
        Promise.all(value.PolygonItem.map(p =>
        {
            return someAsychActionThatReturnPromise(p).then(res => res)
        })).then(data =>
        {
            polygonsarray.push("POLYGON(" + data + ")"));
            
        }).catch(err => return throwError(err));
    }
}

//polygonsarray is still empty in this stage
strPolygonArray = polygonsarray.join();
Guy E
  • 1,775
  • 2
  • 27
  • 55
  • [How do I ask a good question?](https://stackoverflow.com/help/how-to-ask): _"**Describe the problem.** "It doesn't work" isn't descriptive enough to help people understand your problem. Instead, tell other readers what the expected behavior should be. Tell other readers what the exact wording of the error message is, and which line of code is producing it."_ – Andreas Jan 12 '22 at 09:09
  • 1
    Does this answer your question? [Why is my variable unaltered after I modify it inside of a function? - Asynchronous code reference](https://stackoverflow.com/questions/23667086/why-is-my-variable-unaltered-after-i-modify-it-inside-of-a-function-asynchron) – Andreas Jan 12 '22 at 09:10
  • @Andreas - Sorry - type error - I meant polygonsarray. I fixed it. – Guy E Jan 12 '22 at 09:14
  • `polygonsarray` is not `undefined`. You store an empty array in that variable. It's "only" empty. – Andreas Jan 12 '22 at 09:15
  • @Andreas - again - type error - I fixed it. The problem is that it is still empty – Guy E Jan 12 '22 at 09:17
  • 1
    You are not awaiting the `Promise.all().then` promise to get resolved. You just print as part of the synchronously executed code. – trincot Jan 12 '22 at 09:19

1 Answers1

0

You are not awaiting the Promise.all().then() promise to get resolved. You just print as part of the synchronously executed code.

Some other remarks:

  • .then(res => res) has no utility, it just copies one promise into another having the same resolution.

  • err => return throwError(err) is not valid JavaScript. You can just pass throwError as a function reference for the catch callback argument.

  • Instead of asynchronously pushing elements into an array, just return the values to be pushed (which will be the promised values), and after the Promise.all resolves, collect that data into your array in one go.

  • Use async await syntax: it improves the readability of the code.

  • You don't need to call entries() when you don't use the key part. In that case just use values().

Here is how it could look (I excluded the error handling):

async collectPolygons() {
    let polygonsarray : [] = await Promise.all(
        Array.from(this.Polygons.items.values(), async ({PolygonItem}) => {
            if (!PolygonItem) return ""; // This will be filtered out later
            let data = await Promise.all(PolygonItem.map(someAsychActionThatReturnPromise));
            return "POLYGON(" + data.join(",") + ")");
        }) 
    );
    
    let strPolygonArray : string = polygonsarray.filter(Boolean).join(",");
    // ...
}

Seeing you use this, I suppose the code occurs in some method of a class, so if that is your context, add async before the method name. If this is a stand-alone function, you need to add the function keyword too.

Be aware that strPolygonArray will only be assigned a value asynchronously, so if you are tempted to return it, the caller will still have to use an asynchronous pattern to get the actual value (using await or then).

trincot
  • 317,000
  • 35
  • 244
  • 286