可能有一个简单的答案,但我只需要在C#中使用扩展方法(他们甚至在JS中调用它吗?)。
我有一个使用事件的第三方库。在调用事件后,我需要一个名为的函数。我可以通过承诺轻松完成这项工作,但第三方库是在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以允许一个promise(或其他一些回调方法)?
答案 0 :(得分:2)
承诺和事件虽然表面看起来很相似,但实际上解决了Javascript中的不同问题。
Promises提供了一种方法来管理预期结果的异步操作,但是你只知道要花多长时间。
事件提供了一种管理异步操作的方法,其中可能发生,但您不知道它何时(或者甚至是否)会发生。
在Javascript中,没有简单的方法在两者之间“接口”。
但是对于你给出的例子,有一个简单的解决方案:
wRcon.on('disconnect', function() {
console.log('You have been Disconnected!')
wRcon.reconnect()
})
这可能不如您的解决方案那么优雅,如果您的目的是在最后添加更长的.then()
处理程序链,则会发生故障,但它会完成工作。
答案 1 :(得分:0)
您可以以创建承诺的方式包装连接:
const promise = new Promise((resolve) => {
wRcon.on('disconnect', function() {
resolve();
})
}).then(wRcon.reconnect())
然而,这似乎不是使用Promises的理想场所。 Promise定义了单个数据流,而不是定期的事件驱动方式来处理应用程序状态。此设置仅在断开连接后重新连接一次。
答案 2 :(得分:0)
三个/四个选项,第三个/第四个是我个人的偏好:
on
你可以替换on
对象上的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
并期望它具有不同的返回值(例如{{ 1}},因为this
通常是可链接的操作。)
on
)或者您可以添加方法:
onAndAfter
...然后
const original_on = wRcon.on;
wRcon.onAndAfter = function(...args) {
wRcon.on.apply(this, args);
return Promise.resolve();
};
...但我不喜欢修改其他API的对象。
wRcon.onAndAfter('disconnect', function() {
console.log('You have been Disconnected!');
}).then(_ => wRcon.reconnect());
)相反,我想我会给自己一个实用功能(不“可以”“):
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()));
,当调用时,(ab)使用on
来调度回调(作为当前macrotask结束的微任务;使用{{ 1}}如果你只是想让它成为一个普通的[宏]任务)。
您可以将Promise
添加到setTimeout
的内容,有点像after
:
Function.prototype
......然后:
bind
是的,我知道具有讽刺意味的是(一方面)“我不喜欢修改其他类似API的对象”,然后显示修改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;
};
}
});
的根API的选项。 ; - )