将 setTimeout 与递归承诺一起使用



我有以下代码等待交易在以太坊区块链上被挖掘。

function waitForMinedTransaction(txHash, tries = 1) {
  return new Promise(function(resolve, reject) {
    web3.eth.getTransactionReceipt(txHash, function(err, res) {
      if (err) reject(err)
      if (res) resolve(res)
      // nothing yet (retry in 10 sec..)
      console.log(`Attempt #${ tries }...`)
      if (tries > 60) reject("max_tries_exceeded")
      setTimeout(function() { return waitForMinedTransaction(txHash, tries + 1) }, 10000)
    })
  })
}

问题是,当交易被挖掘时(例如,在 10 次尝试之后(,它永远不会得到解决。我确信这与setTimeout和承诺链有关(其中return承诺而不是resolve/reject当前承诺(,但需要一些关于修复它的指示。

我建议将链接逻辑嵌入到promise constructor回调

还要确保在解析或拒绝时退出函数以避免执行其余代码。因此,在调用 resolvereject 之前放置一个return,并不是说返回值有任何意义,而只是为了确保函数的其余代码不会被执行:

function waitForMinedTransaction(txHash) {
    return new Promise(function(resolve, reject) {
        (function attempt(triesLeft) {
            web3.eth.getTransactionReceipt(txHash, function(err, res) {
                if (err) return reject(err);
                if (res) return resolve(res);
                if (!triesLeft) return reject("max_tries_exceeded");
                console.log(`No result. Attempts left: #${ triesLeft }...`);
                setTimeout(attempt.bind(null, triesLeft-1), 10000);
            });
        })(60); // number of retries if first time fails
    });
}

如果你更喜欢在链中有新的承诺(就像你尝试做的那样(,那么诀窍是使用链式承诺来解决,即使用链式调用的返回值:

function waitForMinedTransaction(txHash, triesLeft = 60) {
    return new Promise(function(resolve, reject) {
        getTransactionReceipt(txHash, function(err, res) {
            if (err) return reject(err);
            if (res) return resolve(res);
            console.log(`No result. Attempts left: #${ triesLeft }...`);
            if (!triesLeft) return reject("max_tries_exceeded");
            setTimeout(_ => {
                resolve(waitForMinedTransaction(txHash, triesLeft-1));
            }, 10000);
        });
    });
}

相关内容

  • 没有找到相关文章

最新更新