我有以下代码等待在以太坊区 block 链上挖掘交易。
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
和 promise 链有关(其中 promise 是 return
ed 而不是 resolve
/拒绝
当前的 promise )但需要一些关于修复它的指示。
最佳答案
我建议将链接逻辑嵌入 promise 构造函数回调。
还要确保当您解决或拒绝时,您退出该函数以避免执行其余代码。所以在调用 resolve
和 reject
之前放置一个 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
});
}
如果你更喜欢在链中有新的 promise (就像你试图做的那样),那么诀窍就是用链式 promise 来解决,即用链式调用的返回值:
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);
});
});
}
关于node.js - 将 setTimeout 与递归 promise 一起使用,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/48337362/