Code execution when two events are triggered

This is mainly a linguistic-agnostic question.

If I expect the completion of two events (say, two I / O events or http requests), what is the best template to solve this problem. The only thing I can think of is the following (pseudo-js example).

request1.onComplete = function() { req1Completed = true; eventsCompleted(); } request2.onComplete = function() { req2Completed = true; eventsCompleted(); } eventsCompleted = function() { if (!req1Completed || !req2Completed) return; // do stuff } 

Is this the most effective model or are there more elegant ways to solve this problem?

+7
source share
4 answers

Before going into details, here is something neat that uses lambda functions from the head:

 function makeCountdownCallback(count, callback) { return function() { if (--count == 0) callback(); }; } request1.onComplete = request2.onComplete = makeCountdownCallback(2, function() { // do stuff }); 

This, obviously, assumes that each event fires no more than once and does not use order.

+4
source

jQuery 1.5 has pending values: http://api.jquery.com/category/deferred-object/

You can easily configure them to forward only when certain events have been triggered.

+2
source

Try # 1 : here is a solution that does not require additional global variables:

 request1.onComplete = function() { // register new handler for event2 here, overwriting the old one request2.onComplete = function() { // now they're both done } } request2.onComplete = function() { // register new handler for event1 here, overwriting the old one request1.onComplete = function() { // now they're both done } } 

The handler for each event fires the first one, clears the other old handler and assigns a new one that includes the material that you need to do after both events are completed. Since we re-assign the second handler inside the handler of the first event (depending on what it is), we always know that we finished when the second handler ends.

Try # 2 . Here, something will work if each type of event is different:

 function onBoth(fn) { var last, done = false; return function(e) { if (last && last !== e.type && !done) { fn(); // done done = true; } last = e.type; } } 

For example, this will not warn β€œdone” until the user scrolls and clicks:

 var both = onBoth(function() { alert("done") }); document.addEventListener("scroll", both, false); document.addEventListener("click", both, false); 

Try # 3 . The previous attempt can be modified to work with similar events:

 function onBoth(fn) { var last, done = false; return function(curr) { if (last && last !== curr && !done) { fn(); // done done = true; } last = curr; } } 

... which should be used as follows:

 var check = onBoth(function() { alert("done") }); request1.onComplete = function() { check(arguments.callee); } request2.onComplete = function() { check(arguments.callee); } 

Basically, this checks the execution of two different callbacks, keeping a reference to the last callback executed. Its use is a bit awkward, but it does its job (i.e., it will work if each of the events is executed more than once).

+1
source

One way to do this: http://tobireif.com/posts/waiting_for_two_events/

 Q.spread([ getA(), getB() ], function(a, b) { // Use the results a and b. // Catch errors: }).catch(function(error) { // Minimal for this example: console.log(error); }); 

The lib is https://github.com/kriskowal/q .

0
source

All Articles