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

Symbol SDK获取账户余额时出现未处理Promise拒绝警告问题

解决Symbol SDK查询余额时的UnhandledPromiseRejectionWarning问题

看起来你遇到的UnhandledPromiseRejectionWarning是因为userBalance函数里手动封装Promise的方式有问题——你同时混用了RxJS的错误处理和手动Promise的reject,导致有些错误没有被正确关联到你创建的Promise上,进而出现未捕获的拒绝。

问题根源拆解

  • 在userBalance中,你手动创建了Promise,但在RxJS的catchError里调用reject(err)后又返回了of(err),这会让Observable继续触发后续的subscribe回调,可能导致resolve和reject被多次调用,或者错误没有被正确绑定到当前Promise。
  • 手动封装Promise包裹Observable完全没必要,RxJS本身提供了toPromise()方法,可以直接把Observable转换成Promise,错误处理会更统一。

修改后的完整代码

import * as SymbolSdk from 'symbol-sdk';
import { catchError } from 'rxjs/operators';

const nodeUrl = 'http://localhost:3000';

// 重写userBalance,用RxJS的toPromise替代手动封装Promise
export async function userBalance(userAddress: SymbolSdk.Address, mosaicId: SymbolSdk.MosaicId): Promise<SymbolSdk.UInt64> {
  const repositoryFactory = new SymbolSdk.RepositoryFactoryHttp(nodeUrl);
  const accountHttp = repositoryFactory.createAccountRepository();

  try {
    const accountInfo = await accountHttp.getAccountInfo(userAddress)
      .pipe(
        catchError((err) => {
          // 直接抛出错误,让外层try/catch捕获
          throw err;
        })
      )
      .toPromise(); // 转换为Promise

    // 查找目标mosaic的余额
    const targetMosaic = accountInfo.mosaics.find(mosaic => mosaicId.equals(mosaic.id));
    return targetMosaic?.amount || new SymbolSdk.UInt64([0, 0]);
  } catch (err) {
    // 统一处理错误,抛出后会被调用方的catch捕获
    throw err;
  }
}

if (require.main === module) {
  const promiseList = [];
  const users = ["TCC4A2H6VX4MVBYHBG33JRCL7SI4Z7OKSKUQRNXS", "TBHE2SZCMVGQTDDVSMM6G7KE33IWCXA726WXEV3H", "TBKFTBO4X5EIEHE4LDWVFALJGQU3HCVTAHN2NXCH", "TCWUJ4ENXWC4QYJ4N7ESVUHTBXL6IJ4TTPNFME3F", "TC2X5PCGSOEGX6TPZYTZQZYJBOP2QOPDC4VQ5GCK"];
  const rawMosaicId = "0874BB5FEAAA53C4";

  // 简化promise创建逻辑,去掉不必要的手动Promise封装
  users.forEach(user => {
    const promise = (async () => {
      try {
        const address = SymbolSdk.Address.createFromRawAddress(user);
        const mosaicId = new SymbolSdk.MosaicId(rawMosaicId);
        const amount = await userBalance(address, mosaicId);
        return [user, amount, mosaicId] as [string, SymbolSdk.UInt64, SymbolSdk.MosaicId];
      } catch (err) {
        throw err;
      }
    })();
    promiseList.push(promise);
  });

  Promise.allSettled(promiseList).then((values) => {
    console.log("Chain over");
    values.forEach((settled) => {
      if (settled.status === "fulfilled") {
        const [user, amount, mosaicId] = settled.value;
        console.log(`User ${user}, amount of ${mosaicId.toHex()}: ${amount.toString()}`);
      } else {
        console.log(`Failed to get balance for user, reason: ${settled.reason}`);
      }
    });
  }).catch(console.error);
}

关键改动说明

  1. 重构userBalance函数:

    • 移除手动创建的Promise,改用RxJS的toPromise()方法将Observable转为Promise,错误会自动被Promise的catch捕获。
    • 用try/catch统一处理异步错误,避免RxJS和手动Promise的错误处理冲突。
    • 用find替代循环查找mosaic,代码更简洁高效。
  2. 简化主逻辑中的Promise创建:

    • 去掉不必要的手动Promise封装,直接用async函数返回Promise,错误会自动被Promise.allSettled处理。

这样修改后,所有错误都会被正确捕获,不会再出现UnhandledPromiseRejectionWarning,同时逻辑更清晰,符合Promise和RxJS的最佳实践。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.07 19:02:40