我有以下代码等待事务在以太坊区块链上挖掘。
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
当前承诺有关)但是需要一些关于修复它的指示。
答案 0 :(得分:7)
我建议将链接逻辑嵌入到 promise构造函数回调中。
还要确保在解析或拒绝时退出该函数以避免执行其余代码。所以在调用return
和resolve
之前放一个reject
,而不是返回值有任何意义,但只是为了确保函数代码的其余部分没有执行:
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);
});
});
}