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

回调转异步遇阻:Coinbase API异步改造失败求助

解决回调转async/await的问题,修复Coinbase API调用错误

首先,咱们来拆解你遇到的两个核心问题:

问题1:Cannot read property 'account' of undefined

你这里犯了一个小错误:await API.getAccount(API_Account_BTC)返回的直接就是account对象,不需要再额外加.account层级。原来的回调代码里,API.getAccount的第二个参数里的account就是返回的结果,所以async版本里const account = await ...之后,直接用account.getTransactions就对了。

问题2:no callback - check method signature

这个错误说明你用的Coinbase库的方法只支持回调模式,不原生返回Promise,所以直接用await会报错——因为await后面必须是一个Promise对象。解决办法是把回调风格的函数包装成Promise版本。

完整的改造方案

下面是修正后的可运行代码,我会逐段解释:

首先,如果你用的是Node.js,可以用内置的util.promisify把回调函数转成Promise;如果环境不支持,也可以手动包装。

const util = require('util'); // Node.js内置工具库

// 先把回调风格的方法转成Promise版本
// 包装API.getAccount
const getAccountAsync = util.promisify(API.getAccount);
// 包装account.getTransactions(因为它的回调有三个参数,promisify无法直接处理)
function getTransactionsAsync(account, pagination = null) {
  return new Promise((resolve, reject) => {
    account.getTransactions(pagination, (err, data, pagination) => {
      if (err) reject(err);
      else resolve({ data, pagination });
    });
  });
}

async function Test() {
  let TXs = [];
  const Array_Pending_API = [0];
  try {
    // 获取账户,现在可以用await了
    const account = await getAccountAsync(API_Account_BTC);
    
    // 获取三次交易数据,对应你原来的逻辑
    const { data: tx1Data, pagination: pagination1 } = await getTransactionsAsync(account);
    TXs = TXs.concat(tx1Data);
    
    const { data: tx2Data, pagination: pagination2 } = await getTransactionsAsync(account, pagination1);
    TXs = TXs.concat(tx2Data);
    
    const { data: tx3Data } = await getTransactionsAsync(account, pagination2);
    TXs = TXs.concat(tx3Data);
    
    // 筛选未确认的转出交易
    for (const tx of TXs) {
      if (tx.type === "send" && tx.amount.amount < 0 && tx.network.status !== "confirmed") {
        Array_Pending_API.push(-Number(tx.amount.amount));
      }
    }
    
    // 计算总和
    Pending_API = Array_Pending_API.reduce(getSum);
  } catch (err) {
    console.log("Failed to get transactions:", err);
    Pending_API = 0;
  }
}

// 调用Test函数时要处理Promise,避免未捕获拒绝
// Test().catch(err => console.error("Test function error:", err));

关键细节解释

  1. 回调转Promise:

    • 对于API.getAccount,直接用util.promisify就可以,因为它符合Node.js的标准回调格式(最后一个参数是(err, result))。
    • 对于account.getTransactions,因为它的回调有三个参数(err, data, pagination),util.promisify只会返回第一个成功值(也就是data),所以我们手动包装Promise,把data和pagination一起返回,这样才能处理分页。
  2. 错误处理:

    • 把所有可能出错的await操作放在try/catch里,和你原来的try/catch逻辑对应,捕获API调用的错误。
    • 调用Test()函数的时候,一定要用.catch()处理可能的未捕获错误,避免出现UnhandledPromiseRejectionWarning。
  3. 代码优化:

    • 把原来的for循环改成for...of,更简洁易读。
    • 用对象解构获取data和pagination,代码更清晰。

深入学习async/await的要点

  1. async函数的本质:async函数执行后返回一个Promise,不管你return什么值,都会被包装成Promise.resolve(值)。
  2. await的要求:await后面必须是一个Promise对象,如果不是,会自动被包装成Promise。
  3. 回调转Promise的通用方法:
    • 标准Node.js回调(err优先):用util.promisify。
    • 非标准回调:手动用new Promise((resolve, reject) => { ... })包裹,在回调里调用resolve或reject。
  4. 错误处理:
    • 要么在async函数内部用try/catch捕获await的错误。
    • 要么在调用async函数的时候用.catch()处理。
    • 一定要处理所有Promise的拒绝,否则Node.js新版本会直接终止进程。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.15 06:46:46