• Nick Stenning's avatar
    Don't mix-and-match Angular and native Promises · 5812fc46
    Nick Stenning authored
    Well this was fun to debug.
    
    Not.
    
    So, it seems that in 1.4 (as opposed to 1.2) Angular Promises are
    special, and don't play well with native browser Promises. In
    particular, Angular promises don't resolve until a digest cycle, which
    means that while this test will pass:
    
        it('should resolve', function (done) {
           var resolved = false;
    
           $timeout(function () { resolved = true; });
           .then(function () {
             assert.isTrue(resolved);
           })
           .then(done, done);
    
           $timeout.flush(); // <- this triggers a digest cycle
        });
    
    This one will not -- Mocha will time it out, because the digest cycle
    triggered by `$timeout.flush()` occurs before the fulfillment handlers
    (with the assertions and the call to `done`) are registered:
    
        it('should resolve', function (done) {
           var resolved = false;
           var wait = $timeout(function () { resolved = true; });
    
           $timeout.flush();
    
           wait.then(function () {
             assert.isTrue(resolved);
           })
           .then(done, done);
        });
    
    If that were the whole story, I would be merely mildly displeased. But
    it's not...
    
    The return value of a call to `.then(onFulfilled, onRejected)` is a
    promise of the return value of the `onFulfilled` callback, which is what
    makes Promises chainable. If `onFulfilled` returns a promise, then that
    is (or should be) the promise returned by `.then(...)`. Unfortunately,
    if we actually do this:
    
        it('should resolve', function (done) {
           $timeout(function () {
              return Promise.resolve('abc');
           })
           .then(function (val) {
             assert.equal(val, 'abc');
           })
           .then(done, done);
    
           $timeout.flush(); // <- this triggers a digest cycle
        });
    
    Then again, Mocha will time out on this test. This is probably because
    the returned Promise resolves on runtime `nextTick`, which is *after*
    the call to `$timeout.flush()`, which means it's after the relevant part
    of the digest cycle which processes the fulfillment handlers for the
    Angular-style promise.
    
    ARGH, Angular. Argh.
    5812fc46
Name
Last commit
Last update
h Loading commit data...
scripts Loading commit data...
.hound.yml Loading commit data...
.jscsrc Loading commit data...
.jshintignore Loading commit data...
.jshintrc Loading commit data...
package.json Loading commit data...