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

Solana程序事件发射测试中的错误处理方案咨询

解决Anchor事件测试中RPC异常静默吞掉的问题

原测试代码仅监听事件触发来resolve Promise,但未处理program.rpc.initialize()的执行异常——一旦RPC调用失败,Promise会一直处于pending状态,导致测试无限等待,异常被完全静默。

基础解决方案:捕获RPC执行错误

修改代码,在RPC调用时捕获异常并reject Promise,同时确保清理监听器:

anchor.setProvider(anchor.AnchorProvider.env());
const program = anchor.workspace.Events;

it("Is initialized!", async () => {
  let listener = null;

  try {
    const [event, slot] = await new Promise(async (resolve, reject) => {
      listener = program.addEventListener("MyEvent", (event, slot) => {
        resolve([event, slot]);
      });

      try {
        // 等待RPC调用完成,捕获执行阶段的错误
        await program.rpc.initialize();
      } catch (err) {
        // RPC出错时立即reject,并清理监听器
        reject(err);
        await program.removeEventListener(listener);
      }
    });

    await program.removeEventListener(listener);

    assert.isAbove(slot, 0);
    assert.strictEqual(event.label, "hello");
  } catch (err) {
    // 兜底清理监听器,避免内存泄漏
    if (listener) {
      await program.removeEventListener(listener);
    }
    // 抛出错误,让测试框架识别为测试失败
    throw err;
  }
});

进阶优化:增加事件超时处理

如果担心RPC成功但事件未正常发射的情况,可以添加超时机制,避免无限等待:

anchor.setProvider(anchor.AnchorProvider.env());
const program = anchor.workspace.Events;

it("Is initialized!", async () => {
  let listener = null;
  let timeoutId = null;

  try {
    const [event, slot] = await new Promise(async (resolve, reject) => {
      listener = program.addEventListener("MyEvent", (event, slot) => {
        clearTimeout(timeoutId); // 事件触发后清除超时
        resolve([event, slot]);
      });

      // 设置5秒超时,超时后自动reject
      timeoutId = setTimeout(() => {
        reject(new Error("Timeout: MyEvent was not emitted"));
        program.removeEventListener(listener);
      }, 5000);

      try {
        await program.rpc.initialize();
      } catch (err) {
        clearTimeout(timeoutId); // 出错时清除超时
        reject(err);
        await program.removeEventListener(listener);
      }
    });

    await program.removeEventListener(listener);

    assert.isAbove(slot, 0);
    assert.strictEqual(event.label, "hello");
  } catch (err) {
    if (listener) {
      await program.removeEventListener(listener);
    }
    if (timeoutId) {
      clearTimeout(timeoutId);
    }
    throw err;
  }
});

关键说明

  1. 同步处理RPC和事件:通过await RPC调用,确保任何执行错误都能被捕获并传递给Promise的reject
  2. 监听器清理:无论测试成功或失败,都必须移除事件监听器,避免影响后续测试用例
  3. 超时机制:可选但建议添加,防止因程序逻辑问题导致事件未发射的极端情况

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.09 12:40:25