Skip to content Skip to sidebar Skip to footer

Angular Js Promises Chaining

Ive been trying to figure out promises for the last two days and i gotten this so far. Any guided direction would be great as i think i confused my self. So this is my service, it

Solution 1:

First of all, @sjokkogutten's answer is the way to go for. Putting your business logic as high as possible (eg. in services) makes the app more maintainable and testable.

Please do not use the second parameter of $http.get(...).then(onSuccess, onError) because it is not chainable.

$http.get(...).then(onSuccess).except(onError) is a better pattern.

A few notes about promises

When you are chaining promises, each then callback receives the promise from the previous one.

$http.get(...)
  .then(function (result) {
    return'getCameraDirectory'; // Or $q.resolve('getCameraDirective'), doesn't matter
  })
  .then(function (result2) {
    // result2 is 'getCameraDirectory'
  });

When working with promises, it is important to always return something! It is easy to forget one return and your promise chain will eventually resolve to undefined.

Your example chains some methods, but these methods do not return anything. This means that the next chained callback does not receive parameters. At last, saveMedia() isn't returning anything, so the whole promise chain resolves to undefined.

Note that you have only one return statement in the whole example.

Rejecting

Suppose in one of your callbacks you want to break the chain based on a condition.

You need to reject the promise. All directly chained thens are not called anymore.

$http.get(...)
  .then(function (result) {
    if (result.length > 0) {
      return result;
    } else {
      return$q.reject('result is empty'); // or throwing error
    }
  })
  .then(function (result2) {
    // result2 is non empty!
  })
  .catch(function (message) {
    // this callback is called when result is empty OR when the $http.get call rejects (eg. returns 404)// Return something if you want to chain furtherreturn'Back on track';
  })
    .then(function (result3) {
      // result3 === 'Back on track'// This callback is only called when coming from `except`
    })
    .catch(function (message2) {
      // This callback is called when previous 'except' or 'then' is rejecting
    });

Solution 2:

$http is already returning a promise, so there is no need to use $q.defer() when calling a service. Instead, I would recommend placing all your $http request in a separate service/service:

app.factory('DataService', function($http, $cordovaFileTransfer) {
  var getCameraDirectory = function() {
    return$http.json("/api/...") // returns a promise
  };

 var setCameraMode= function() {
    return$http.json("/api/...") 
  };

 var getCameraDirectory = function() {
    return$http.json("/api/...") 
  };

 var captureMedia = function() {
    return$http.json("/api/...") 
  };

 var saveMedia = function() {
    return$cordovaFileTransfer.download(url, targetPath, options, trustHosts) // I am not sure, but I am assuming that $cordovaFileTransfer.download() is returning a promise. 
  };

  return {
    getCameraDirectory: getCameraDirectory,
    setCameraMode: setCameraMode,
    captureMedia: captureMedia,
    saveMedia: saveMedia
  }
});

In your controller, you can now resolve your promises using then

myApp.controller('MyController', function ($scope, DataService) {     
    DataService.getCameraDirectory().then(
      function(){ //resolve getCameraDirectory // getCameraDirectory successcallback
      },
      function(){
        // getCameraDirectory errorcallback
      }).then( // resolve setCameraMode function(){
          // setCameraMode successcallback
        },
        function(){
          // setCameraMode errorcallback
        }).then( // resolve captureMedia function(){
            // captureMedia successcallback
          },
          function(){
            // captureMedia errorcallback
          }).then(// resolve saveMediafunction(){
              // saveMedia successcallback
            },
            function(){
              // saveMedia errorcallback
            })   
});

Note that I have not actually implemented the above code, but should provide you with an outline.

Post a Comment for "Angular Js Promises Chaining"