开发者

running code when two events have triggered

This is mostly a language-agnostic question.

If I'm waiting for two events to complete (say, two IO eve开发者_StackOverflownts or http requests), what is the best pattern to deal with this. One 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 pattern, or are there more elegant ways to solve this issue?


Before even going into the details, here's something neat that takes advantage of lambda functions off the top of my 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 at most once, and doesn't take advantage of order.


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

You can easily set them up to call back only when some events have been triggered.


Try #1: Here's a solution that doesn't 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 whichever event fires first will clear the other's old handler and assign a new one that includes the stuff you need to do after the completion of both events. Because we re-assign the second handler inside the handler of the first event (whichever that is), we always know we're done when that second handler finishes.

Try #2: Here's something that will work if each event type 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 won't alert "done" until the user has both scrolled and clicked:

var both = onBoth(function() {
    alert("done")
});

document.addEventListener("scroll", both, false);
document.addEventListener("click", both, false);

Try #3: The previous try can be modified to work for 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 like this:

var check = onBoth(function() {
    alert("done")
});

request1.onComplete = function() {
    check(arguments.callee);
}

request2.onComplete = function() {
    check(arguments.callee);
}

Basically, this checks that two different callbacks have executed by storing a reference to the most recently executed call back. Its usage is a little clunky, but it gets the job done (i.e. it will still work if each of the events executes more than once).


One way to do it: 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 at https://github.com/kriskowal/q .

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜