Skip to content

Instantly share code, notes, and snippets.

@metamatt
Created June 11, 2015 23:00
Show Gist options
  • Star 3 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save metamatt/6ab462818114833b7ee1 to your computer and use it in GitHub Desktop.
Save metamatt/6ab462818114833b7ee1 to your computer and use it in GitHub Desktop.
Replace Angular $q with Bluebird

The good: this works (see also http://stackoverflow.com/a/23984472/275581, angular/angular.js#6697, http://plnkr.co/edit/ggMzDwnkzMOc0MccdVEu?p=preview). You'll have Bluebird promises that interact with the digest cycle and even internal Angular code that thinks it's using $q will actually be using Bluebird.

The bad: you'll probably trip over a bunch of places where your own code, or library code like ui-router, thinks it's ok to create rejected promises and never attach error handlers, because $q is silent about that and Bluebird complains about it. You did know that $timeout.cancel() rejects a promise and you always catch that rejection, right?

app.config(['$qProvider', function($qProvider) {
// Tell Angular to create Bluebird promises instead of $q promises.
$qProvider.$get = function() {
function QBird(resolver) {
return new Promise(resolver);
}
QBird.defer = function() {
var deferred = {};
deferred.promise = new Promise(function(resolve, reject) {
deferred.resolve = resolve;
deferred.reject = reject;
});
return deferred;
};
QBird.reject = Promise.reject;
QBird.when = Promise.resolve;
QBird.all = Promise.all;
return QBird;
};
});
app.run(['$rootScope', function ($rootScope) {
Promise.setScheduler(function (cb) {
$rootScope.$evalAsync(cb);
});
}]);
@Rush
Copy link

Rush commented Jul 22, 2015

Indeed it seems to work, nice! Any ides about fixing the ui-router verbosity?

@Rush
Copy link

Rush commented Jul 22, 2015

  Promise.onPossiblyUnhandledRejection(function(error, promise, oldHandler){
    // ui-router returns rejected promises, prevent logs for them
    if(error.message.match(/transition (superseded|prevented|aborted|failed)/)) {
      return;
    }
    console.warn("%c" + error.stack, "color: red");
  });

@yutin1987
Copy link

good!!!

@duanefields
Copy link

Ugh - I haven't been able to get this to work at all, it never loads the controllers or views into the template. Here's my implementation (coffescript) attached. Any ideas what I'm missing here? Angular 1.4.5

Promise = require 'bluebird'

angular.module 'qbird', []
.config [
  '$qProvider', ($qProvider) ->
    $qProvider.$get = ->
      QBird = (resolver) ->
        new Promise(resolver)

      QBird.defer = ->
        deferred = {}
        deferred.promise = new Promise((resolve, reject) ->
          deferred.resolve = resolve
          deferred.reject = reject
          return
        )
        deferred

      QBird.reject = Promise.reject
      QBird.when = Promise.resolve
      QBird.all = Promise.all
      QBird
]
.run [
  '$rootScope', ($rootScope) ->
    Promise.setScheduler (cb) ->
      $rootScope.$evalAsync cb
]

Promise.onPossiblyUnhandledRejection (error, promise, oldHandler) ->
  # ui-router returns rejected promises, prevent logs for them
  return if error.message.match(/transition (superseded|prevented|aborted|failed)/)
  console.warn '%c' + error.stack, 'color: red'

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment