Angular Js Promises Chaining
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 then
s 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"