有没有一种方法可以监听多个事件

Is there a way to listen to multiple events?

本文关键字:监听 事件 方法 一种 有没有      更新时间:2023-09-26

例如,我想在所有事件发生时触发回调:

on(['aEvent', 'bEvent', 'cEvent'], callback)

其中回调函数从aEventbEventcEvent获得参数的数组(或者可能是对象)。

更新:关于我想要实现的内容。

我正在构建一个向用户公开API的警报系统,这样当一些事件发生时,用户就可以对它们做出响应。有时,用户希望仅在aEventbEvent都发生时才进行响应。这个要求就成了问题。

使用ES2015和RxJs.zip:

function multiSubscribe(elem, events) {
    return Rx.Observable.zip(...events.map(
        event => Rx.Observable.fromEvent(elem, event)
    )).subscribe(arrayOfEvents => {
        // do whatever
    });
}

我很难理解这在现实世界中什么时候会被实际使用,这让我不确定我是否理解你真正想做什么,但你可以编写自己的函数来跟踪一系列事件中的每一个发生的时间:

function listenMultiple(elem, events, callback) {
    var eventList = events.split(" ");
    var cnt = 0;
    var results = {};
    eventList.forEach(function(event) {
        function localHandler(e) {
            this.removeEventListener(event, localHandler);
            results[event] = e;
            ++cnt;
            if (cnt === eventList.length) {
                callback(results);
            }
        }
        elem.addEventListener(event, localHandler);
    });
}

用法:

listenMultiple(elem, "aEvent bEvent cEvent", function(results) {
    // all three events have happened
});

注意:为了避免对给定事件进行多次计数,这将在事件发生时删除侦听器。


对这种情况进行多次响应是复杂的,因为这取决于你希望它如何工作,因为有很多方法可以配置,而你还没有解释你希望如何工作。我能想到的最简单的方法就是在它启动时让它重新初始化。这将等待所有事件发生,然后当发生时,调用相同的函数来重新设置。这将在最后一个事件发生时重新启动所有计数器,因此它将忽略在系列的最后一个发生之前发生的任何其他事件的任何盈余。

function listenMultiple(elem, events, callback) {
    var eventList = events.split(" ");
    var cnt = 0;
    var results = {};
    eventList.forEach(function(event) {
        function localHandler(e) {
            this.removeEventListener(event, localHandler);
            results[event] = e;
            ++cnt;
            if (cnt === eventList.length) {
                callback(results);
                // configure for next sequence
                listenMultiple(elem, events, callback);
            }
        }
        elem.addEventListener(event, localHandler);
    });
}

编辑

现在,您已经阐明了当各种事件多次出现在其中时您想要什么,这会变得更加复杂,因为您必须为每个事件保持N个状态级别。这里有一个适用于DOM事件的方案(因为这是我测试它的最简单方法),但它肯定可以适用于任何类型的事件:

// pass a list of ids and a list of events and a callback
function listenMultiple(ids, events, callback) {
    var eventList = events.split(" ");
    var idList = ids.split(" ");
    if (idList.length !== eventList.length) {
        throw new Error("Number of ids and events must be the same");
    }
    var eventCntrs = {};
    var results = [];
    eventList.forEach(function(event, index) {
        var key = event + idList[index];
        eventCntrs[key] = 0;
        
        function localHandler(e) {
            // get our current cnt for this event
            var cnt = eventCntrs[key];
            log("click on: ", this.id, ", cnt = ", cnt);
            // if we don't yet have any results for this cnt, 
            // then initialize the results object for this cnt
            if (!results[cnt]) {
                results[cnt] = {_cntr: 0};
            }
            // save this event object
            // and count it
            results[cnt][key] = {time: Date.now()};
            ++results[cnt]._cntr;
            
            // count this event
            ++eventCntrs[key];
            
            // if this fills out a result set, then fire the callback
            if (results[cnt]._cntr === eventList.length) {
                callback(results[cnt]);
                // clear item saved in results array so it can be garbage collected
                delete results[cnt];
            }
        }
        document.getElementById(idList[index]).addEventListener(event, localHandler);
    });
}
listenMultiple("test1 test2 test3", "click click click", function(result) {
    log("callback: ", result);
})
// diagnostic function for showing results
function log(args) {
    var str = "";
    for (var i = 0; i < arguments.length; i++) {
        if (typeof arguments[i] === "object") {
            str += JSON.stringify(arguments[i]);
        } else {
            str += arguments[i];
        }
    }
    var div = document.createElement("div");
    div.innerHTML = str;
    var target = log.id ? document.getElementById(log.id) : document.body;
    target.appendChild(div);
}
log.id = "output";
#output {
  margin-top: 30px;
}
Click any sequence of the three buttons.<br><br>Each time a combination of each one of the three is completed, a result will be output via the callback.<br><br>
<button id="test1">1</button><button id="test2">2</button><button id="test3">3</button>
<div id="output">

您可以像一样尝试

document.getElementById('mouseenter',master_handler,false)
document.getElementById('mouseout',master_handler,false)
document.getElementById('mouseclick',master_handler,false)

所有事件都绑定到一个处理程序。这就是处理程序的

function master_handler(event){
    if(event.type=="mouseenter"){
       Some something special
     }
     if(event.type=="mouseout"){
       Some something special
     }
     if(event.type=="click"){
       Some something special
     }
}