简体   繁体   English

使用For Loop链接和嵌套的诺言

[英]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 对于每个游戏,每个媒体资源执行一次aSync通话
  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(). 我尝试使用Promises.all(),但由于在then()中有一些异步调用,因此我无法正确同步它。

How can I make sure to get the object Games filled with all its properties? 如何确保让对象游戏充满其所有属性?

You should use Promise.all like this. 您应该这样使用Promise.all 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 . 基本上,您需要将所有三个aSyncCallGetProperty异步调用都包装在Promise.all ,等待它们真正完成,然后将结果分配给对象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. @Lewis的代码似乎正确,但我无法确定numberOfGames是什么。 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. 假设它是您的问题中使用的整数(而不是其他答案中所使用的数组),那么这里是不带嵌套的.then()的另一个改写版本。

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);
                    });
  });

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM