环境:
假设有三个事件发生在某个应用程序的三个独立部分,该事件应由两个控制器处理。应用程序调度程序负责从应用程序的所有部分发送/接收事件,并且此调度程序应具有异步事件队列。
在某些情况下,三个事件中的两个与某些属性相关但名称不同,只有一个应传递给控制器,另一个可能被丢弃。
问题:
目前,我有一个'队列',它实际上只是将事件反弹给控制器,这是无益的,因为如果只有一个事件在那里,我无法比较队列中的两个事件。
那么我如何确保事件应该暂停在队列中一段时间?我想一个超时功能可以做到这一点,但有更好的方法吗?
为了给予应有的信用,合并事件的想法受到Cocoa的启发,我基本上都在尝试做类似的事情。
答案 0 :(得分:2)
我对Cocoa知之甚少,但我认为它将旧事件替换为最新事件,直到事件能够被分派到应用程序(即如果应用程序由于某种原因而忙)。我不确定您的特定用例是什么,但如果您想对事件进行速率限制,我会像这样使用setTimeout
:
function Dispatcher(controllers) {
this.controllers = controllers;
this.events = [];
this.nextController = 0;
}
Dispatcher.prototype = {
_dispatch: function (i) {
var ev = this.events.splice(i, 1);
this.controllers[this.nextController].handle(ev);
this.nextController = (this.nextController + 1) % this.controllers.length;
},
notify: function (ev) {
var index = -1, self = this, replace;
function similer(e, i) {
if (e.type === ev.type) {
index = i;
return true;
}
}
replace = this.events.some(similar);
if (replace) {
this.events[i] = ev;
} else {
// it's unique
index = this.events.push(ev) - 1;
setTimeout(function () {
self._dispatch(index);
}, 100);
}
}
};
只需使用该事件调用notify
(确保有type
属性或类似内容),它就会处理魔法。不同类型的事件将使用自己的setTimeout
唯一处理。
我没有测试过这段代码,所以可能存在错误。
答案 1 :(得分:1)
我认为超时功能可以解决问题,但有更好的方法吗?
不,确实没有。
如果在同一个运行循环中调度事件,通常可以使用setTimeout(..., 0)
。所以实现看起来像这样:
var eventQueue = [];
var handlerTimer = -1;
function fireEvent(event, params) {
eventQueue.push([event, params]);
window.clearTimeout(handlerTimer);
handlerTimer = window.setTimeout(resolveQueue, 0);
}
function resolveQueue() {
// process eventQueue and remove unwanted events...
// then dispatch remaining events
eventQueue = [];
}
如果需要处理来自不同运行循环的事件(例如mouseup
和click
等本机事件),则需要使用除0以外的某些超时值。具体值取决于多长时间你想累积事件。