You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

使用setTimeout与递归Promise时以太坊交易挖矿等待未resolve问题

Fixing the Unresolved Promise in Ethereum Transaction Mining Wait Function

Let's break down why your promise never resolves and how to fix it.

The Root Cause

Your current code creates an outer promise when waitForMinedTransaction is first called, but when you recursively call the function inside setTimeout, you're just returning a new promise without linking its outcome to the outer promise's resolve or reject handlers. That means the original promise stays stuck in a pending state forever—never getting resolved or rejected, even when the transaction is mined.

Fixed Promise-Based Version

Here's the corrected version that properly chains the promise results:

function waitForMinedTransaction(txHash, tries = 1) { 
  return new Promise(function(resolve, reject) { 
    web3.eth.getTransactionReceipt(txHash, function(err, res) { 
      if (err) {
        return reject(err);
      }
      if (res) {
        return resolve(res);
      }
      // Log attempt and check retry limit
      console.log(`Attempt #${ tries }...`) 
      if (tries > 60) {
        return reject("max_tries_exceeded");
      }
      // Recursively call the function, then pass its result to the outer promise
      setTimeout(function() {
        waitForMinedTransaction(txHash, tries + 1)
          .then(resolve) // Forward successful result to outer resolve
          .catch(reject); // Forward errors to outer reject
      }, 10000);
    }); 
  }); 
}

Key Changes:

  • When we recursively call waitForMinedTransaction, we use .then(resolve) and .catch(reject) to pass the inner promise's outcome directly to the outer promise's handlers. This connects the entire promise chain properly, so the original promise will resolve/reject when the transaction is found or the retry limit is hit.
  • Added explicit return statements after reject/resolve to prevent unnecessary code execution.

A Cleaner Async/Await Alternative

If you prefer more readable, linear code, here's an async/await version that achieves the same goal without nested callbacks:

async function waitForMinedTransaction(txHash, tries = 1) {
  try {
    const receipt = await web3.eth.getTransactionReceipt(txHash);
    if (receipt) {
      return receipt;
    }

    console.log(`Attempt #${ tries }...`);
    if (tries > 60) {
      throw new Error("max_tries_exceeded");
    }

    // Wait 10 seconds before retrying
    await new Promise(resolve => setTimeout(resolve, 10000));
    // Recursively call and return the result
    return waitForMinedTransaction(txHash, tries + 1);
  } catch (err) {
    throw err;
  }
}

This version uses async/await to flatten the async logic, making it easier to follow. The recursive call's result is automatically passed up as the return value of the current function, so the promise chain stays intact.

内容的提问来源于stack exchange,提问作者FloatingRock

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.15 03:50:05