-1

I understand that we could use .then to make sure the order of asynchronous calls:

return doTask1()
    .then(function () {
        return doTask2()
    })

But sometimes it will be convenient to have a light and to be able to say: wait and don't execute task2 until a light is set to GREEN; the light is a variable initially set to RED, and can be set to GREEN by task1 or other functions.

Does anyone know if it is possible to accomplish this?

Edit 1: I think being able to express this is particularly useful when we need several tasks to be ended to set the light green, and we don't know/mind the order of these tasks. .then cannot do this easily, because we don't know the order of these tasks.

Edit 2: Regarding my light, I had asked a more specific question. In one word, it is the message another application B sends by postMessage that we are waiting for. At the moment, I have written the following code (which is in a resolve), which works more or less (I have not tried if making only ONE function with their common part will work).

task1: ['codeService', '$window', '$q', function (codeService, $window, $q) {
    return codeService.task1().then(function () { // task1 sends a request to another application B by postMessage
        var deferred = $q.defer();
        $window.addEventListener("message", function (event) {
            if (event.data.req === "task1ReturnFromB") deferred.resolve(event.data)
        }, { once: true });
        return deferred.promise
    })
}],
task2: ['codeService', 'task1', '$window', '$q', function(codeService, task1, $window, $q) {
    return codeService.task2().then(function () { // task2 sends a request to Application B by postMessage
        var deferred = $q.defer();
        $window.addEventListener("message", function (event) {
            if (event.data.req === "task2ReturnFromB") deferred.resolve(event.data) 
        }, { once: true });
        return deferred.promise
    })
}]

So in this specific case, postMessage sent by Application B triggers the event. In a more general case, I guess we could probably trigger an event by eg, dispatchEvent, in one application?

Community
  • 1
  • 1
SoftTimur
  • 5,630
  • 38
  • 140
  • 292
  • You need to define an event handler - `function onGreenLight()` for example, and then execute that in the part of the code that sets the light colour. This isn't asynchronous or synchronous - this is event driven. You don't wait for it to turn green - you do something when it does. – Reinstate Monica Cellio Mar 12 '17 at 19:48
  • The `onGreenLight` can be triggered by the end of `doTask1()` and other functions. What's the best way to trigger an event in JavaScript? – SoftTimur Mar 12 '17 at 19:51
  • The code that sets the light to either red or green - you execute the event handler there. – Reinstate Monica Cellio Mar 12 '17 at 20:08
  • @SoftTimur Best not to mix and match asynchronicity models. Use a promise representing the light becoming green, and `then` on that (or a combination of that with some other promises). – Asad Saeeduddin Mar 12 '17 at 20:58
  • You haven't told us anything about how your light works (other than what it can't do). What kind of APIs does it provide? – JLRishe Mar 13 '17 at 05:53

2 Answers2

0

Using Promises would be the best way to do this. Promises are objects that execute a function and when that function is done the THEN-function is executed. But only when the function give a result back.

Example

var task1 = new Promise(function(resolve, reject) {
     var value = 1;
     setTimeout(function(){
          resolve(value);
     }, 1000);

});

var task1.then(function(value){
     // After one second, do something with your value here
});
Marc van Nieuwenhuijzen
  • 1,637
  • 1
  • 14
  • 22
0

You haven't told us anything about the API for your light so I can only guess what it's like. Presuming it's an event driven model, you can convert it to a promise, and do this:

function waitForGreenLight() {
    return new Promise(function (resolve) {
        $window.addEventListener("message", function (event) {
           if (event.data.req === "task2ReturnFromB") {
               resolve(event.data) 
           }
        }, { once: true });
    });
}

return doTask1()
    .then(waitForGreenLight)
    .then(doTask2);

If your light doesn't provide events, you could have a waitForGreenLight that periodically polls it until it's green. The code to use waitForGreenLight would remain the same.

function waitForGreenLight() {
    return new Promise(function (resolve) {
        var handle = setInterval(function () { 
            if (myLight.color === 'green') { 
                resolve();
                clearInterval(handle);
            }
        }, 100);
    });
}
JLRishe
  • 99,490
  • 19
  • 131
  • 169
  • Thank you... I thought it was impossible... Could you provide also a code of a light that provides events, so that the first exemple will be complete? – SoftTimur Mar 13 '17 at 06:27
  • @SoftTimur It sounds like what you're asking for would be outside the scope of this question, which is about waiting for the light to turn green. If you want to wrap your light in an event-based API, please ask a separate question about that. And as I've pointed out twice, you haven't told us anything about how your light's API works. Before asking me for more code, please provide the information I've asked of you. Without that, I can't help you any further. – JLRishe Mar 13 '17 at 11:07
  • Please see my update... I guess, in a general case, `lightHandler` in your code could be `$window`, `document`, etc. And we could trigger an event by `dispatchEvent`... right? – SoftTimur Mar 13 '17 at 14:37
  • @SoftTimur Thank you very much. Could you please see the edited version of my first sample? – JLRishe Mar 13 '17 at 15:06