struggling to get promises working correctly in angularjs service provider i've read the docs as well as numerous examples (here, here and here) and i think i've got my syntax ok (although obviously something is wrong)
app module and controller look like
var myApp = angular.module('myApp', []);
myApp.controller('Controller_1', ['$scope', 'Service_1', function($scope, Service_1) {
var myName = "Ben";
Service_1.slowService(myName)
.then(Service_1.fastService(name));
$scope.myName = myName;
}]);
the service (with the slow function) looks like this:
myApp.service('Service_1', function($q) {
this.slowService = function (name) {
var deferred = $q.defer();
console.log('Start of slowService:', name, Date.now());
setTimeout(function() {
console.log('setTimeout name:', name, Date.now());
if(name){
name = 'Hello, ' + name + " is learning Angularjs";
alert(name);
console.log('name:', name);
deferred.resolve(name);
} else {
deferred.reject('No name supplied !');
}
}, 3000);
return deferred.promise;
};
this.fastService = function(name){
console.log('Start of fastFunction:', name, Date.now());
alert('Hello ' + name + ' - you are quick!');
};
});
console output looks like this:
Start of slowService: Ben 1420832940118
Start of fastFunction: result 1420832940122
setTimeout name: Ben 1420832948422
name: Hello, Ben is learning Angularjs
The fastService is starting before the slowService completes, despite using a deferred object / promise in Service_1 and a .then in the controller...
Can anyone point out what's wrong with the code ?
jsfiddle is here
EDIT: put the fast function in the service so there's no confusion with hoisting etc - still the same result - js fiddle updated
The fastService is starting before the slowService completes
That is because you are executing the function fastService before slowService async callback runs.Instead you would want to provide the reference of the function. i.e .then(Service_1.fastService(name)); should be .then(Service_1.fastService); or .then(function(name){ Service_1.fastService(name); }); otherwise fastservice will just run right away, before the async part of the slowService runs.
Use $timeout with that the advantage is that it already returns a promise so you do not need to create a deferred object and resulting in deferred anti-pattern.
myApp.service('Service_1', function($q, $timeout) { //<-- Inject timeout
this.slowService = function (name) {
console.log('Start of slowService:', name, Date.now());
return $timeout(function() {
console.log('setTimeout name:', name, Date.now());
if(name){
name = 'Hello, ' + name + " is learning Angularjs";
return name; //return data
}
//Reject the promise
return $q.reject('No name supplied !');
}, 3000);
};
//...
});
and when consuming just chain through:
Service_1.slowService(myName)
.then(Service_1.fastService);
So instead of timeout even if you are using $http in your original method just return the promise from http rather than creating a deferred object. Also just keep in mind when you use the syntax .then(Service_1.fastService); and if you are referring to this context in the fast service it wont be the service instance.
The way you are passing your function to then() part is not correct.
Pass it like this :
Service_1.slowService(myName)
.then(function(){fastFunction(name)});
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With