如何实现带once和on方法的Promise?结合EventEmitter方案求教
实现融合Promise与EventEmitter的事务处理对象(参考web3.js风格)
核心思路
要实现像web3.js那样同时支持on/once事件监听和then/catch Promise链式调用的对象,核心是让Promise实例拥有EventEmitter的事件管理能力。具体做法是:
- 用EventEmitter(或自定义实现)处理事件的订阅与触发
- 创建Promise管理事务的异步生命周期(完成/失败)
- 将EventEmitter的
on/once/off方法挂载到Promise实例上,实现流畅的链式调用
完整代码实现(Node.js环境)
const { EventEmitter } = require('events'); function createTransaction() { // 初始化事件发射器 const emitter = new EventEmitter(); // 创建Promise,封装事务逻辑 const transactionPromise = new Promise((resolve, reject) => { console.log('事务启动'); // 模拟txn_id生成逻辑(1秒后生成) setTimeout(() => { const txnId = `txn_${Math.random().toString(36).slice(2, 11)}`; emitter.emit('idCreated', txnId); }, 1000); // 模拟剩余时间推送(每秒更新一次) let remainingSeconds = 5; const timeTimer = setInterval(() => { remainingSeconds--; emitter.emit('timeLeft', remainingSeconds); if (remainingSeconds === 0) { clearInterval(timeTimer); // 事务完成,返回结果 resolve({ status: 'completed', txnId: `txn_${Math.random().toString(36).slice(2, 11)}` }); } }, 1000); // 可选:模拟事务失败场景 // setTimeout(() => { // clearInterval(timeTimer); // const error = new Error('事务执行超时'); // emitter.emit('error', error); // reject(error); // }, 3000); }); // 将EventEmitter的方法绑定到Promise实例,实现链式调用 transactionPromise.on = emitter.on.bind(emitter); transactionPromise.once = emitter.once.bind(emitter); transactionPromise.off = emitter.off.bind(emitter); return transactionPromise; } // 使用示例 createTransaction() .once('idCreated', (txnId) => { console.log('txn_id已生成:', txnId); }) .on('timeLeft', (seconds) => { console.log('剩余预估时间:', `${seconds}秒`); }) .then((result) => { console.log('事务执行完成:', result); }) .catch((error) => { console.error('事务执行失败:', error); });
浏览器环境适配
如果是浏览器环境,没有Node.js的events模块,可以自己实现一个简易版EventEmitter:
class SimpleEventEmitter { constructor() { this.eventMap = new Map(); } on(eventName, handler) { if (!this.eventMap.has(eventName)) { this.eventMap.set(eventName, []); } this.eventMap.get(eventName).push(handler); return this; } once(eventName, handler) { const onceHandler = (...args) => { handler(...args); this.off(eventName, onceHandler); }; this.on(eventName, onceHandler); return this; } off(eventName, handler) { if (!this.eventMap.has(eventName)) return; const handlers = this.eventMap.get(eventName); this.eventMap.set(eventName, handlers.filter(h => h !== handler)); } emit(eventName, ...args) { if (!this.eventMap.has(eventName)) return; this.eventMap.get(eventName).forEach(handler => handler(...args)); } } // 替换createTransaction里的EventEmitter为SimpleEventEmitter即可
关键细节说明
- 事件与Promise的联动:事务中的关键节点(如txn_id生成、剩余时间更新)通过
emitter.emit触发事件,事务完成/失败通过Promise的resolve/reject处理 - 链式调用支持:通过将EventEmitter的方法绑定到Promise实例,实现像web3.js那样的
on().once().then()链式调用 - 内存泄漏防范:事务完成或失败时,要及时清除定时器等异步任务,避免内存泄漏
- 错误处理:可以同时通过
on('error')监听错误和catch()捕获错误,提升灵活性
内容的提问来源于stack exchange,提问作者CodingWithRoyal
相关产品推荐
相关产品推荐

