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

Node.js回调与Promise误区:批量查询XRP余额异常求助

问题根源分析

你的问题核心在于异步操作没有被正确等待,导致API连接在账户查询完成前就被断开了:

  1. 你用了回调式的fs.readdir,它不属于Promise链的一部分,所以api.connect()的then块在触发fs.readdir后,会直接执行后续的then(也就是调用api.disconnect()),完全不等目录读取后的账户查询操作完成。
  2. 就算目录读取完成,files.forEach里的getAccount是异步Promise操作,但forEach不会等待这些Promise完成,所以所有查询请求还在处理中,连接就被切断了,自然打印不出余额,进程直接结束。
修复方案

我们需要把所有异步操作都纳入Promise链,确保所有账户查询完成后再断开连接。这里有两种写法,你可以选自己习惯的:

方案1:使用async/await(更直观易读)

'use strict';
const RippleAPI = require('ripple-lib').RippleAPI;
const testFolder = '/home/ripple/.keystore';
const fs = require('fs').promises; // 改用Promise版本的fs模块
const api = new RippleAPI({server: 'wss://s1.ripple.com'});

function getAccount(address) {
  console.log("getting info for :" + address);
  return api.getAccountInfo(address).then(info => {
    const balance = info.xrpBalance;
    console.log("balance of " + address + " is " + balance);
    return balance;
  });
}

// 用async函数包裹,让异步代码同步化写法
api.connect()
  .then(async () => {
    // 等待目录读取完成,拿到所有地址文件
    const files = await fs.readdir(testFolder);
    // 遍历每个地址,生成查询余额的Promise数组
    const balanceQueries = files.map(address => {
      console.log(address);
      return getAccount(address);
    });
    // 等待所有余额查询Promise完成
    await Promise.all(balanceQueries);
  })
  .then(() => api.disconnect())
  .then(() => console.log("done and disconnected"))
  .catch(console.error);

方案2:纯Promise链式调用(不用async/await)

如果你还不熟悉async/await,也可以用纯Promise的写法:

'use strict';
const RippleAPI = require('ripple-lib').RippleAPI;
const testFolder = '/home/ripple/.keystore';
const fs = require('fs').promises;
const api = new RippleAPI({server: 'wss://s1.ripple.com'});

function getAccount(address) {
  console.log("getting info for :" + address);
  return api.getAccountInfo(address).then(info => {
    const balance = info.xrpBalance;
    console.log("balance of " + address + " is " + balance);
    return balance;
  });
}

api.connect()
  .then(() => fs.promises.readdir(testFolder)) // 读取目录,返回Promise给下一个then
  .then(files => {
    files.forEach(address => console.log(address));
    // 生成所有查询Promise,用Promise.all等待全部完成
    return Promise.all(files.map(getAccount));
  })
  .then(() => api.disconnect())
  .then(() => console.log("done and disconnected"))
  .catch(console.error);
关键改动说明
  • 改用fs.promises.readdir:把回调式的文件读取改成Promise版本,这样它能融入外层的Promise链,确保目录读取完成后再执行后续操作。
  • 使用Promise.all:它会等待传入的所有Promise都成功resolve后才继续执行下一个步骤,这样就能保证所有账户的余额查询都完成后,再断开API连接。
  • 移除forEach的异步隐患:forEach不会等待异步操作完成,改用map生成Promise数组,配合Promise.all就能正确等待所有查询结束。

这样修改后,代码会先连接API,读取目录里的所有地址,逐个查询余额并打印,等所有查询完成后再断开连接,最后打印"done and disconnected",完全符合你的预期。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.15 08:46:30