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

如何从async函数中正确返回PromiEvent?

如何从async函数正确返回PromiEvent?

这个问题的核心在于async函数的特性:async函数会自动将任何返回值(哪怕是已经是Promise的对象)包装成一个全新的Promise实例。而你用new Web3PromiEvent()创建的实例,虽然本身继承了Promise,但同时附加了on等事件相关方法——当async函数返回它时,这些附加方法会被外层的包装Promise覆盖,导致你拿到的只是一个普通Promise,自然找不到on处理器。

解决方法:放弃用async声明inner函数

既然async函数会强制包装返回值,那我们改用普通函数来编写inner逻辑,用.then()处理异步操作,这样就能直接返回原始的PromiEvent实例,保留它的事件监听能力:

const Web3PromiEvent = require('web3-core-promievent')

function sleep() {
  return new Promise((resolve) => setTimeout(resolve, 1000))
}

// 改用普通函数,不用async
function inner() {
  const pe = new Web3PromiEvent()
  
  sleep().then(() => {
    pe.eventEmitter.emit('done', 'ok')
    pe.resolve('ok')
  })
  
  return pe
}

async function main() {
  const pe = inner()
  pe.on('done', console.log)
  const res = await pe
  console.log(res)
}

main()

为什么这个方法有效?

普通函数不会对返回值做额外包装,所以你拿到的pe就是原始的PromiEvent实例——它既是一个可以await的Promise,同时拥有on方法来监听事件,完美契合你的需求。

如果一定要用async函数怎么办?

如果业务逻辑必须用async/await,那你需要手动把PromiEvent的事件方法挂载到async函数返回的Promise上。不过这种方式比较hack,不推荐,因为会破坏Promise的原生结构:

async function inner() {
  const pe = new Web3PromiEvent()
  
  await sleep()
  pe.eventEmitter.emit('done', 'ok')
  pe.resolve('ok')
  
  // 把PromiEvent的on方法绑定到async返回的Promise上
  const promise = pe
  promise.on = (...args) => pe.eventEmitter.on(...args)
  return promise
}

但还是更推荐第一种方案,保持代码的简洁性和语义正确性。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.04.28 18:14:10