简体   繁体   中英

Chained and Nested promises with For Loop

I am trying to get each property of my games within chained promises (Each of the property is coming from a different async calls).

Logic of my algorithm:

  1. Check the Network and Get the smart contract address
  2. Register the contract containing the addresses of all the Games
  3. Get the number of Games
  4. For each game, perform one aSync call per property
  5. Print all the games and details (here I am not able to get the updated object)

Code:

  var games = [];
  window.addEventListener('load', function() {
    // Check the Network and assign the smart contract address

    web3.eth.net.getId()
      .then(function(networkId) {
        let contractAddressRegistry;
        if (networkId == 1) {
          contractAddressRegistry = "0xQWERTYUIOPQWERTYUIOPQWERTY"
        } else {
          contractAddressRegistry = "0x12345678901234567890123456"
        }
        return contractAddressRegistry;
      })
      .then(function(contractAddressRegistry) {
        let contractRegistry = new web3.eth.Contract(contractAbiRegistry, contractAddressRegistry);

        contractRegistry.methods.numberOfGames().call()
          .then(function(numberOfGames) {

            for (let i = 0; i < numberOfGames; i++) {
              let game = {};
              game.propertyA = aSyncCallGetPropertyA(i); // Promise
              game.propertyB = aSyncCallGetPropertyB(i); // Promise
              game.propertyC = aSyncCallGetPropertyC(i); // Promise
            }
            games.push(game);
          })
      })
      .then(function() {
        console.log(games) // Empty
      })
  })

I tried used Promises.all() but I am not able to sync it properly as some async calls are within a then().

How can I make sure to get the object Games filled with all its properties?

You should use Promise.all like this. Basically, you need to wrap all three aSyncCallGetProperty async calls in Promise.all for waiting until they really finish then assign the results to object game .

whatever
    .then(function(contractAddressRegistry) {
        let contractRegistry = new web3.eth.Contract(contractAbiRegistry, contractAddressRegistry);
        return contractRegistry.methods.numberOfGames().call();
    })
    .then(function(numberOfGames) {
        return Promise.all(numberOfGames.map(() => {
            return Promise.all([
                aSyncCallGetPropertyA(),
                aSyncCallGetPropertyB(),
                aSyncCallGetPropertyC()
            ]).then(results => {
                let game = {};
                game.propertyA = results[0];
                game.propertyB = results[1];
                game.propertyC = results[2];
                return game;
            });
        }));
    })
    .then(function(games) {
        console.log(JSON.stringify(games));
    })

@Lewis' code seems right but I can not make sure what numberOfGames is. Assuming that it's an integer as used in your question (not an array as treated in the other answer) here is a further rephrased version without nested .then() s.

window.addEventListener('load', function() {
  web3.eth.net.getId()
              .then(networkId => networkId === 1 ? "0xQWERTYUIOPQWERTYUIOPQWERTY"
                                                 : "0x12345678901234567890123456")
              .then(contractAddressRegistry => new web3.eth.Contract(contractAbiRegistry, contractAddressRegistry).methods.numberOfGames().call())
              .then(numberOfGames => Promise.all(Array(numberOfGames).fill()
                                                                     .map(_ => Promise.all([aSyncCallGetPropertyA(),
                                                                                            aSyncCallGetPropertyB(),
                                                                                            aSyncCallGetPropertyC()]))))
              .then(function(games){
                      games = games.map(game => ({propertyA: game[0],
                                                  propertyB: game[1],
                                                  propertyC: game[2]}));
                      doSomethingWith(games);
                    });
  });

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