Promises in AngularJS
Father and Son
One morning, a father says to his son:
"Go and get the weather forecast, son!"
-
Son creates a promise with his dad at the door when he leaves
-
The dad decides if the weather tomorrow is good:
- He will go for fishing
- He will stay back
Outcome
A) Weather forecast retrieved! Sunshine :-)
( promise was fulfilled )
Outcome
B) Weather forecast retrieved! Cloudy and rain :-(
( promise was fulfilled )
Outcome
C) Couldn't get the weather forecast :-/
(promise was rejected!)
// function somewhere in father-controller.js
var makePromiseWithSon = function() {
// This service's function returns a promise, but we'll deal with that shortly
SonService.getWeather()
// then() called when son gets back
.then(function(data) {
// promise fulfilled
if (data.forecast==='good') {
prepareFishingTrip();
} else {
prepareSundayRoastDinner();
}
}, function(error) {
// promise rejected, could log the error with: console.log('error', error);
prepareSundayRoastDinner();
});
};
Controller: FatherCtrl
app.factory('SonService', function ($http, $q) {
return {
getWeather: function() {
// the $http API is based on the deferred/promise APIs exposed by the $q service
// so it returns a promise for us by default
return $http.get('http://fishing-weather-api.com/sunday/afternoon')
.then(function(response) {
if (typeof response.data === 'object') {
return response.data;
} else {
// invalid response
return $q.reject(response.data);
}
}, function(response) {
// something went wrong
return $q.reject(response.data);
});
}
};
});
Service: SonService
Javascript :single threaded
Javascript :single threaded
console.log("1");
setTimeout(function(){console.log("2");},3000);
console.log("3");
setTimeout(function(){console.log("4");},1000);
Javascript executes each line in sequence.
So you told js:
write 1: js writes 1
wait 3 seconds and then write 2: ok I'll wait 3 seconds...now what?
write 3: ok I'll write 3, by the way, the 3 seconds is not up.
wait 1 second and then write 4: ok I'll wait 1 second...
then js waits .99999 seconds ... and writes 4
then waits some more and writes 2
What is a promise?
An assurance that we will get a result from an action at some point in the future, let’s see the two possible results of a promise:
- A promise is said to be fulfilled when we get a result from that action (meaning that we get a response, regardless of whether the response is good or bad)
- A promise is said to be rejected when we don’t get a response(for instance if we were retrieving some data from an API and for some reason we never got a response because the API endpoint was down etc.)
Why Promises?
We need promises because we need to make decisions based on the possible results of our call
$q?????
- This $q service is heavily inspired by the Q library of Kris Kowal.
- $q service that provide deferred and promise implementations.
- it will let you write your custom promises as well (so you can resolve or reject a promise when appropriate).
- Deferred represents a task that will finish in the future
- A number of Angular services return promises: $http, $interval, $timeout,...........
better die.......
Deferred
- Initially this task is in the status pending.
- Eventually the task completes successfully or it fails.
- In the former case the status of deferred will be resolved while in the latter case the status will be rejected.
var deferred=$q.defer();
var deferred = $q.defer();
// deferred contains the promise to be returned
// to resolve (fulfill) a promise use .resolve
deferred.resolve(data);
// to reject a promise use .reject
deferred.reject(error);
semantics
// this
$http.get('/api/v1/movies/avengers')
.success(function(data, status, headers, config) {
$scope.movieContent = data;
});
// is the same as
var promise = $http.get('/api/v1/movies/avengers');
promise.then(
function(payload) {
$scope.movieContent = payload.data;
});
- All promise returns are single objects
- For example, for $http.get, the promise returns an object with four keys: data, status, headers, and config.
- Sample code:http://plnkr.co/edit/kACAcbCUIGSLRHV0qojK?p=preview
Promises and Services
Subtitle
angular.module('atTheMoviesApp', [])
.controller('GetMoviesCtrl',
function($log, $scope, movieService) {
$scope.getMovieListing = function(movie) {
var promise =
movieService.getMovie('avengers');
promise.then(
function(payload) {
$scope.listingData = payload.data;
},
function(errorPayload) {
$log.error('failure loading movie', errorPayload);
});
};
})
.factory('movieService', function($http) {
return {
getMovie: function(id) {
return $http.get('/api/v1/movies/' + id);
}
}
});
What about post processing??
separation of concerns
Subtitle
...
.factory('movieService', function($http, $log, $q) {
return {
getMovie: function(movie) {
var deferred = $q.defer();
$http.get('/api/v1/movies/' + movie)
.success(function(data) {
deferred.resolve({
title: data.title,
cost: data.price});
}).error(function(msg, code) {
deferred.reject(msg);
$log.error(msg, code);
});
return deferred.promise;
}
}
});
Handling problems in nested service calls
this.getMovie = function(movie) {
return $http.get('/api/v1/movies/' + movie)
.then(
function (response) {
return {
title: response.data.title,
cost: response.data.price
});
},
function (httpError) {
// translate the error
throw httpError.status + " : " +
httpError.data;
});
};
...and now the error returned will be a single string, not the $http error with data, status, headers and config properties.
Doing more than one thing at a time
$q.all lets you trigger several callbacks at the same time, and use a single then function to join them all together.
service('asyncService', function($http, $q) {
return {
loadDataFromUrls: function(urls) {
var deferred = $q.defer();
var urlCalls = [{ url: 'ajax1.html' },{ url: 'ajax2.html' },{ url: 'ajax3.html' }];
angular.forEach(urls, function(url) {
urlCalls.push($http.get(url.url));
});
// they may, in fact, all be done, but this
// executes the callbacks in then, once they are
// completely finished.
$q.all(urlCalls)
.then(
function(results) {
deferred.resolve(
JSON.stringify(results))
},
function(errors) {
deferred.reject(errors);
},
function(updates) {
deferred.update(updates);
});
return deferred.promise;
}
};
});
Referred Links
Promises
By mohammad sirajuddin Rayyan
Promises
How promises works
- 200