0

Thanks to @bergi for the answer. FWIW. Here's some code that outputs: -

Kept1234OKAfter Keptinterloperafter 2nd

<!DOCTYPE html>
<html>
<body>
  <p id="demo"></p>
  <script>

    var keep;
    var myPromise = new Promise(res => {keep = res;})
    var demo = document.getElementById("demo");

    for (var x=1; x<5; x++){
        setTimeout(function(){
            var myId = x;
            return function()
                        {
                            myPromise.then(()=>{
                                    demo.innerHTML += myId;
                                    if (myId == 2) {
                                        setTimeout(function(){demo.innerHTML += "after 2nd"},0);
                                        myPromise.then(()=>{demo.innerHTML += "OK"})
                                    }
                                    });
                        }
            }(),x*500);                
}

wait(3000).then(()=>{
    keep();
    demo.innerHTML += "Kept";
    setTimeout(function(){demo.innerHTML += "After Kept";
    myPromise.then(()=>{demo.innerHTML += "interloper"})  },0)
    });

function wait(time) {
    return new Promise(resolve => 
        {
            setTimeout(resolve, time)
        });
}
</script>
</body>
</html>

No where in the "duplicate" is the relevant information "So when your "event" happens while the queue is still being worked on, yes the callback does get queued up. ". This is a unique question.

NB: This question asks specifically about a JS event that fires while the .THENable chain is unwinding. For example, if there were 4 events partially completed and waiting on a promise that was just resolved and the first 2 had completed execution but Mr New Event tries THEN and continues immediately. IIUYC you say this can't happen as ALL pending-promise events complete as an atomic unit before a click or setTimeout can get in? But how did they get in when the Promise was still unresolved?

If I have several different events with .THENs waiting on a promise is the release order guaranteed to be FIFO?

For the sake of argument I'll assume the answer is "yes" but the more complicated question is what happens to a new event that now tries to THEN on an already resolved Promise? Does it immediately execute thus jumping the residual queue of pending resolution waiters?

I'm worried that we must logically single-thread access to promises for things like postMessage if we need to process messages in order :-(

For example (some justification explanation code below) if I want to post messages to my service worker then I will have to manage my own array-queue, push my message on and then "if myQueueLen == 1 setTimeout(postQueueProcessor,0)" and the queue processor event will call/fire itself till empty.

This would render promises as pretty bloody awful so I must be getting it wrong. Please advise.

    var fireTravelEvent = 
    function(msg,callback)
    {
        try {
            currActive.postMessage(msg);
            console.log("Msg Sent to SW");
            if (callback) callback();
        } catch (e) {
            if (e.name == "InvalidStateError" || e.name == "TypeError") {
                navigator.serviceWorker.ready
                .then(reg => {
                        currActive = reg.active;
                        fireTravelEvent(msg, callback)})
            } else {
                throw e;
            }
        }
    }   

As long as Javascript Promises support FIFO resolution the above will work but other cases will potentially have new THENers coming in with new events before ALL pending THENers have been satisfied?

McMurphy
  • 1,235
  • 1
  • 15
  • 39
  • Multiple `.then()` handlers on the SAME promise are executed in FIFO order. I honestly can't understand what the rest of your question is about to know how that applies to what else you're doing. – jfriend00 Jul 10 '17 at 12:40
  • Thanks for the quick replies. @jfriend00 thanks, that answers the first part. mplungjan very similar and IIUC tells me that a "new" THEN on a resolved promise will execute immediately in-line, so guys this all says we must implement our own message queues with controllable JS "event blocks event, no yeilding, no promises" events or FIFO can not be guaranteed? Have I made my point/concerns clearly? This is horrendous :-( – McMurphy Jul 10 '17 at 12:46
  • Better phrasing: - "Is the processing/exhaustion of the .then() handlers on the SAME promise executed atomically?" I'm starting to think there's absolutely no way the answer can be "Yes" :-( – McMurphy Jul 10 '17 at 12:52
  • @McMurphy Yes of course it is, all asynchronous JS is atomic. No two callbacks run at the same time. – Bergi Jul 10 '17 at 14:03
  • "*What happens to a new event that now tries to THEN on an already resolved Promise? Does it immediately execute?*" No, all promise `then` callbacks are always executed asynchronously, i.e. queued for later – Bergi Jul 10 '17 at 14:04
  • @bergi Do you have a reference to the spec you're pointing to? Can someone else explain to Bergi the chalk & cheese differences between my question and the one he/she claims is a duplicate? WRT "Yes of course it is, all asynchronous JS is atomic." are you serious? Have you worked with promises? – McMurphy Jul 10 '17 at 17:36
  • @McMurphy if you refer to the specs mentioned in the answer to the duplicate, they're linked. – Bergi Jul 10 '17 at 19:00
  • @McMurphy Regarding atomicity, I was referring to a single callback execution that [cannot be interrupted](https://stackoverflow.com/q/2734025/1048572). Of course multiple callbacks might run in any order depending on when the events they're subscribed to fire. – Bergi Jul 10 '17 at 19:03
  • Regarding the updated question, with an even firing while multiple promises callbacks execute: the duplicate should answer even that with "*then callbacks are executed in the order of their originating calls to `then`*". Hint: a promise callback does *never* get executed immediately, it is *always* scheduled for later. So when your "event" happens while the queue is still being worked on, yes the callback does get queued up. That said, this [won't happen](https://stackoverflow.com/q/19743354/1048572), as `onmessage` events never fire in between promise callbacks. – Bergi Jul 10 '17 at 19:07
  • OK, this is the relevant bit: - "So when your "event" happens while the queue is still being worked on, yes the callback does get queued up. " Cool! The problem is a "potential duplicate" that @mplungjan pointed me to but since deleted :-( said the opposite. Any spec references anyone? Example? This would really make a lot more sense. But a performance hungry designer may well have said "Why force a callback when we know it's resolved? Rock on!" Also I see not intermediate state of half-resolved or half-pregnant in the specs. Only 3 hard states a promise can be in. "Always Callback" cool! – McMurphy Jul 10 '17 at 23:06
  • Regardless of anything else, the "So when your "event" happens while the queue is still being worked on, yes the callback does get queued up. " is ***not*** in the duplicate. Please remove your censorship? – McMurphy Jul 10 '17 at 23:13
  • I think mplungjan suggested [this question](https://stackoverflow.com/q/43592229/1048572), but I don't see how it contradicts the information given here. – Bergi Jul 11 '17 at 00:02
  • @McMurphy No, callbacks are specifically not allowed to be called immediately (and it doesn't even boost performance). See [here](https://stackoverflow.com/q/36932244/1048572) for some reasoning – Bergi Jul 11 '17 at 00:17
  • Thank you. Good news! And thanks for the extra question pointers. This was the text that through me from a response marked as answer and voted up "As expected: then callback will get called immediately in this case if then was called after promise has already resolved." – McMurphy Jul 11 '17 at 00:42

0 Answers0