JavaScript / NodeJS – 添加承诺作为扩展方法

这可能是一个简单的答案,但我只能使用扩展方法(他们甚至在JS中调用?)在C#中..

我有一个使用事件的第三方库。 我需要一个函数在事件被调用后被调用。 我可以通过一个承诺很容易地做到这一点,但第三方库是在ES6之前编写的,并没有内置的承诺。下面是一些示例代码 –

wRcon.on('disconnect', function() { console.log('You have been Disconnected!') }) 

理想情况下,我想能够实现这样的事情 –

 wRcon.on('disconnect', function() { console.log('You have been Disconnected!') }).then(wRcon.reconnect()) 

所以总结一下我的问题,我如何扩展wRcon.on以允许承诺(或其他callback方法)?

承诺和事件,虽然表面上看起来很相似,但实际上解决了Javascript中的不同问题。

Promise提供了一种pipe理asynchronous操作的方法,可以预期结果,但是您不知道需要多长时间。

事件提供了一种pipe理asynchronous操作的方法, 可能会发生什么情况,但是您不知道何时(甚至是否)会发生。

在Javascript中,没有简单的方法来在两者之间“接口”。

但是对于你给出的例子,有一个简单的解决scheme:

 wRcon.on('disconnect', function() { console.log('You have been Disconnected!') wRcon.reconnect() }) 

这可能不像你的解决scheme那样优雅,如果你的意图是在最后附加一个更长的.then()处理程序链,但是它会完成工作。

你可以用一种可以创造承诺的方式来包装连接:

 const promise = new Promise((resolve) => { wRcon.on('disconnect', function() { resolve(); }) }).then(wRcon.reconnect()) 

不过,这似乎不是使用Promise的理想场所。 Promises定义了一个单一的数据stream,而不是一个重复的事件驱动的方式来处理应用程序状态。 这种设置只会在断开连接后重新连接一次。

三/四个选项给你,第三个/第四个是我个人的喜好:

取代

可以replacewRcon对象上的wRcon

 const original_on = wRcon.on; wRcon.on = function(...args) { original_on.apply(this, args); return Promise.resolve(); }; 

…你可以使用的几乎和你一样(注意_ => ):

 wRcon.on('disconnect', function() { console.log('You have been Disconnected!'); }).then(_ => wRcon.reconnect()); 

…但是我很乐意这么做,尤其是因为wRcon其他部分可能会呼吁on并期望它具有不同的回报价值(比如, this通常是一个可链接的操作)。

添加一个新的方法( onAndAfter

或者你可以添加一个方法:

 const original_on = wRcon.on; wRcon.onAndAfter = function(...args) { wRcon.on.apply(this, args); return Promise.resolve(); }; 

…然后

 wRcon.onAndAfter('disconnect', function() { console.log('You have been Disconnected!'); }).then(_ => wRcon.reconnect()); 

…但我不喜欢修改其他API的对象。

实用程序方法(独立,或在Function.prototype

相反,我想我会给自己一个效用函数(这不是 “可靠的”):

 const after = (f, callback) => { return function(...args) { const result = f.apply(this, args); Promise.resolve().then(callback).catch(_ => undefined); return result; }; }; 

…然后像这样使用它:

 wRcon.on('disconnect', after(function() { console.log('You have been Disconnected!'); }, _ => wRcon.reconnect())); 

这就创build了一个新的函数,当被调用的时候,(ab)使用Promise来安排callback(作为当前macros任务结束时的一个微任务;如果你只是希望它是一个普通的[macros]任务)。

你可以添加一些你添加到Function.prototype ,有点像bind

 Object.defineProperty(Function.prototype, "after", { value: function(callback) { const f = this; return function(...args) { const result = f.apply(this, args); Promise.resolve().then(callback).catch(_ => undefined); return result; }; } }); 

…接着:

 wRcon.on('disconnect', function() { console.log('You have been Disconnected!'); }.after(_ => wRcon.reconnect())); 

是的,我意识到讽刺(一方面)“我不想修改其他API的对象”,然后显示修改Function的根API的选项。 😉