2

Consider the following code:

        function wait(ms) {
            var deferred = $.Deferred();
            setTimeout(deferred.resolve, ms);
            return deferred.promise();
        }

        var starter, promiseOne;
        starter = $.Deferred();
        promiseOne = starter.then(function () {
            console.log("Calling promiseOne");
            return wait(2000);
        }).done(function () {
            console.log('promiseOne done');
        });
        starter.resolve();

        var now=new Date().getTime();
        var stop=now+5000;
        while (stop>new Date().getTime()){}
        console.log('timeout finished');

By running it, I am getting the following results:

Calling promiseOne
timeout finished
promiseOne done

I was thinking that promise callbacks are sent to Event queue, so I was expecting these results:

timeout finished
Calling promiseOne
promiseOne done

If not sending to Event queue,I 'd expect:

Calling promiseOne
promiseOne done
timeout finished

Could someone explain to me why am I getting the first triad?

P.S. By replacing then with done, I am getting:

Calling promiseOne
promiseOne done
timeout finished
Unknown developer
  • 5,414
  • 13
  • 52
  • 100
  • Don't use jQuery deferreds. – Bergi Feb 09 '16 at 18:38
  • Why? And then what to use? – Unknown developer Feb 09 '16 at 18:49
  • [Because](http://stackoverflow.com/q/23744612/1048572) (And apparently they don't do what you were thinking, which they indeed *should* do). There are [many alternatives](https://promisesaplus.com/implementations) all of which [will work with jQuery](http://stackoverflow.com/a/31327725/1048572) – Bergi Feb 09 '16 at 18:54
  • I've spent so much time with jQuery promises and now... What do you think about jQuery 3.0? Also, Angular promises are Promises/A+ compliant? – Unknown developer Feb 09 '16 at 19:13
  • Yes, both of them will be working. Though I've spent some time to read the code of the jQuery 3.0 promise implementation and wonder whether I really should recommend it. Well, it meets the test suite. – Bergi Feb 09 '16 at 19:16
  • Promise callbacks are called 'microtasks' and are "usually scheduled for things that should happen straight after the currently executing script" See https://jakearchibald.com/2015/tasks-microtasks-queues-and-schedules/ – Eric Jun 11 '16 at 00:46

1 Answers1

1

The jQuery implementation of the Promises isn't ECMASCRIPT compliant, for example, jQuery promises (actually) aren't resolved at the next event loop. jQuery promises will be es-compliant with the upcoming third version: jQuery.Deferred is now Promises/A+ compatible.

Note: did you try to run starter.resolve() in a async function? for example: window.setTimeout(starter.resolve, 0); Doing that your test-case should work as expected. By the way, this isn't a Promise-bug but a simple jQuery-bad-implementation, remember that jQuery was born some year before the Promise specification

In order to reply at:

Are promise callbacks sent to Event queue?

Promise callbacks are simple javascript callbacks, so, as each simple javascript callback, even promise callbacks are attached to the event loop.

Hitmands
  • 13,491
  • 4
  • 34
  • 69
  • Not every simple Javascript callback is attached to the Event loop. For example: [1,2,3,4,5].every(test); callback **test** is not attached to the event loop... – Unknown developer Feb 09 '16 at 19:17
  • did you mean `at the next eventloop`? – Hitmands Feb 09 '16 at 19:37
  • I mean the above callback does not get out of normal execution flow and waits till the execution stack gets empty as to be called from the event queue and being executed. It is manipulated completely from JS engine.I do not understand what you mean by the next eventloop... – Unknown developer Feb 09 '16 at 20:01
  • 2
    "jQuery promises (actually) aren't resolved at the next event loop" isn't quite correct. jQuery and all Promise/A+ libs resolve synchronously - [demo](http://jsfiddle.net/2nhfxwyy/1/). It's not the timing of *resolution* that's the issue with jQuery, it's when callbacks are fired in response to resolution. A more accurate statement is unfortunately also more verbose - eg, "if a jQuery Deferred is resolved in the *same* event turn as `.then()` etc callbacks are attached, those callbacks will fire in the that *same* event turn, not a future event turn as required by Promises/A+". – Roamer-1888 Feb 10 '16 at 16:40