Angular promises using multiple http requests - javascript

I have read a few forum posts before on angular promises but can't get it to work in my instance. I am using nodejs /locomotive for the backend and Angular form the frontend.
I have the following code in a controller, basically I want to use the path to slides.path, how would I go about doing this using promises? any help would be gratefully received.
function ProductCtrl($scope, $http, $q) {
$scope.events = [];
$scope.times = [];
var html = [];
var chapters = [];
var path;
//var paPromise = $q.defer();
$http({
url: '/show',
method: 'GET',
params: { eventid:$scope.$routeParams.eventid}
}).success(function(response, code) {
$scope.events = response;
angular.forEach($scope.events.slides, function(slide) {
$http({
url: '/upload',
method: 'GET',
params: {uploadid: slide.upload.toString()}
}).success(function(response, code) {
return "http://www.example.com/"+response.path;
},path);
slide.path = path;
chapters.push(slide);
});
});
}

You can use $q.all do get this multiple promise problem done. Like this:
function ProductCtrl($scope, $http, $q) {
$scope.events = [];
$scope.times = [];
var html = [];
var path;
function fetchChapter() {
var chapters = [];
var httpPromise = $http({
url: '/show',
method: 'GET',
params: {
eventid: $scope.$routeParams.eventid
}
});
//Return the value http Promise
return httpPromise.then(function (response) {
$scope.events = response;
var promises = [];
angular.forEach($scope.events.slides, function (slide) {
var inPromise = $http({
url: '/upload',
method: 'GET',
params: {
uploadid: slide.upload.toString()
}
}).then(function (response, code) {
//each promise makes sure, that he pushes the data into the chapters
slide.path = "http://www.example.com/" + response.path;
chapters.push(slide);
});
//Push the promise into an array
promises.push(inPromise);
});
//return the promise from the $q.all, that makes sure, that all pushed promises are ready and return the chapters.
return $q.all(promises).then(function () {
return chapters;
});
});
}
fetchChapter().then(function(chapters){
//populate here
});
}
The httpPromise will return the promise from $q.all.
EDIT: How to fetch the data then
Wrap a function around, i did with fetchChapter and pass a function into the then there will be the value you need as a parameter.

Related

$http post request breaks rest of angularjs code

I just started learning Angularjs and I am facing a peculiar problem. If I get my $http post to work, the rest of my code doesn't, and the other way around- if everything else works my $http post doesn't. Does it have to do with my controller? Should I use a factory?
angularjs file:
var app = angular.module('emailApp', []);
app.controller('EmailController', function($scope, $http) {
$http({
method: "post",
url: "php.php",
data: $.param($scope.composeEmail),
headers: {'Content-Type': 'application/x-www-form-urlencoded'}
}).then(function(response){
$scope.data = response.data;
});
$scope.isPopupVisible = false;
$scope.isComposePopupVisible= false;
$scope.composeEmail = {};
$scope.activeTab = "inbox";
$scope.sentEmails = [];
$scope.sendEmail = function() {
$scope.isComposePopupVisible = false;
$scope.composeEmail.date = new Date();
$scope.sentEmails.push($scope.composeEmail);
};
$scope.showComposePopup = function() {
$scope.composeEmail = {};
$scope.isComposePopupVisible = true;
};
$scope.showPopup = function(email) {
$scope.isPopupVisible = true;
$scope.selectedEmail = email;
};
});

not able to get function return value in angularjs http request

I am getting undefined for the value returned by the function which is an http request. So I am calling http request inside http.
bmgApp.controller('cmpUserSoftwares', function($scope, $http) {
$scope.records = {};
$http({
method: 'GET',
url: 'http://megabot/mautonew/wp-json/bmg-comp-listing/v1/company/1'
}).then(function successCallback(response) {
// this callback will be called asynchronously
// when the response is available
$scope.records = response.data;
for (var i = 0; i < $scope.records.length; i++) {
console.log($scope.records[i]);
angular.forEach($scope.records[i], function(value, key) {
if (key == "maincategoryid") {
value = getSoftwareCategory(value);
}
console.log(value + ' : ' + key);
});
}
function getSoftwareCategory(value) {
$http({
method: 'GET',
url: 'http://megabot/mautonew/wp-json/bmg-comp-listing/v1/software-category/' + value
}).then(function successCallback(response) {
var software_category = response.data;
console.log(software_category);
return software_category;
}, function errorCallback(response) {
console.log("Error");
});
}
/*angular.forEach($scope.records, function(value, key){
console.log( $scope.records[key].value + ' : ' + key);
});*/
//console.log(response.statusText);
}, function errorCallback(response) {
console.log("Error");
});
});
The console.log inside getSoftwareCategory function is returning the value but not getting assigned to value variable. I am getting undefined
getSoftwareCategory is calling an asynchronous call and from inside and it doesn't actually return anything. (The return value of the inner then() handler is not returned when the parent function is called)
Although this could probably be done better, as a first step, return the promise from getSoftwareCategory and do the value assignment using a then() block.
EDIT: New code based on discussion in comments
$http({
method: 'GET',
url: 'http://megabot/mautonew/wp-json/bmg-comp-listing/v1/company/1'
}).then(function successCallback(response) {
function getSoftwareCategory(record) {
return $http({
method: 'GET',
url: 'http://megabot/mautonew/wp-json/bmg-comp-listing/v1/software-category/' + record.maincategoryid
}).then(function successCallback(response) {
record.maincategoryid = response.data;
return record;
}, function errorCallback(response) {
console.log("Error");
});
}
var records = response.data;
var promises = records.map(function (record) {
return getSoftwareCategory(record);
})
return $q.all(promises).then(function (results) {
$scope.records = results;
});
}, function errorCallback(response) {
console.log("Error");
});
You are doing it in the wrong way I think you are not familier with async programming in JavaScript. The value in value = getSoftwareCategory(value); will be always undefined because your getSoftwareCategory is not returning any value. To handle this kind of task in your code you should first read about promises in javascript. So your code will be like this after modifying this
bmgApp.controller('cmpUserSoftwares', function($scope, $http) {
$scope.records = {};
$http({
method: 'GET',
url: 'http://megabot/mautonew/wp-json/bmg-comp-listing/v1/company/1'
}).then(function successCallback(response) {
// this callback will be called asynchronously
// when the response is available
$scope.records = response.data;
for (var i = 0; i < $scope.records.length; i++) {
console.log($scope.records[i]);
angular.forEach($scope.records[i], function(value, key) {
if (key == "maincategoryid") {
getSoftwareCategory(value).then(software_category => {
console.log(software_category)
});
}
console.log(value + ' : ' + key);
});
}
function getSoftwareCategory(value) {
return $http({
method: 'GET',
url: 'http://megabot/mautonew/wp-json/bmg-comp-listing/v1/software-category/' + value
}).then(function successCallback(response) {
var software_category = response.data;
console.log(software_category);
return software_category;
}, function errorCallback(response) {
console.log("Error");
});
}
/*angular.forEach($scope.records, function(value, key){
console.log( $scope.records[key].value + ' : ' + key);
});*/
//console.log(response.statusText);
}, function errorCallback(response) {
console.log("Error");
});
});

Use output from services to controllers

I want to result of my $http.get from my service to my controller.
myserviceSample.js
function messagesService($q,$http){
var messages;
$http({
method: 'GET',
url: 'http://api.com/feedback/list'
})
.then(function success(response){
messages = response.data;
console.log(messages);
},function error(response){
console.log('error'+ response);
});
console.log(messages);
return {
loadAllItems : function() {
return $q.when(messages);
}
};
}
})();
mycontrollerSample.js
function MessagesController(messagesService) {
var vm = this;
vm.messages = [];
messagesService
.loadAllItems()
.then(function(messages) {
console.log(messages);
vm.messages = [].concat(messages);
});
}
})();
The above code results gives undefined output.
What i miss?
$q.when object does expect promise/object to make it working. In your case you have to pass promise object to $q.when as you are doing $http.get call. Here messages object doesn't hold promise of $http.get, so you could change the implementation of method like below.
Service
function messagesService($q,$http){
var messages = $http({
method: 'GET',
url: 'http://api.com/feedback/list'
})
.then(function success(response){
return response.data;
},function error(response){
return $q.reject('Error Occured.');
});
return {
loadAllItems : function() {
return $q.when(messages);
}
};
}
Then controller will resolve that promise & .then will do the trick
function MessagesController(messagesService) {
var vm = this;
vm.messages = [];
messagesService
.loadAllItems()
.then(function(messages) {
console.log(messages);
vm.messages = [].concat(messages);
});
}
Note: Using $q to create a custom promise, is considered as bad pattern when you have $http.get method there(which does return
promise itself)
Improved Implementation
function messagesService($q, $http) {
var messages, getList = function() {
return $http({
method: 'GET',
url: 'http://api.com/feedback/list'
})
.then(function success(response) {
messages = response.data
return response.data;
}, function error(response) {
return $q.reject('Error Occured.');
});
};
return {
loadAllItems: function() {
if (!data)
return getList(); //return promise
else
return $q.resolve(messages); //return data
}
};
};

call $http in response of another http - angular js

I am new on angular JS. I am tried to implement $http in the response of $http.
My issue is that when i call $http in response of anoter $http. It doesn't show the data on view. The view is rendered before the second $http call. I have used promises but no luck. Here is the code from other answer which i used by changing a little.
angular.module('App', [])
.controller('Ctrl', function($scope, resultsFactory) {
resultsFactory.all().then(
function(res){
$scope.results = res;
},
function(err){
console.error(err);
}
);
})
.factory('resultsFactory', function($http, $timeout, $q) {
var results = {};
function _all(){
var d = $q.defer();
$http({
url: url,
method: 'POST'
}).then(function (response) {
var f = {};
f.id = response.data.id;
f.name = response.data.name;
$http({
url: url,
data: "id="+response.data.parent_id,
method: 'POST'
}).then(function (response1) {
f.parentname = response1.name;
d.resolve(f);
});
});
return d.promise;
}
results.all = _all;
return results;
});
The id and name is shown properly on view but it is showing nothing for parent name. I have debug it. It is undefined when rendering view. After rendering it is setting their value to parentname. Can any one help me to resolve this issue?
You shouldn't need a deferred for this: just chain the promises:
return $http({
url: url,
method: 'POST'
}).then(function (response) {
var data = {};
data.id = response.data.id;
data.name = response.data.name;
return $http({
url: url,
data: "id="+response.data.parent_id,
method: 'POST'
}).then(function (response1) {
data.parentname = response1.name;
return data;
});
});
You overwrote your d variable...
.factory('resultsFactory', function ($http, $timeout, $q) {
var results = {};
function _all() {
var d = $q.defer();
$http({
url : url,
method : 'POST'
}).then(function (response) {
var secondD = {};
secondD.id = response.data.id;
secondD.name = response.data.name;
$http({
url : url,
data : "id=" + response.data.parent_id,
method : 'POST'
}).then(function (response1) {
secondD.parentname = response1.name;
secondD.resolve(d);
});
});
return d.promise;
}
results.all = _all;
return results;
});

How to call ajax from service in AngularJS?

I have Employee controller which is having property Id, Name , Specification. I have made one Employee service which is having ajax call and get employee list. But every time getting '' in User.
When i debug the code i found that it call success first and then it goes for Ajax call.
When i do ajax call without service it works fine.
angular.module('EmployeeServiceModule', [])
.service('EmployeeSer', ['$http',function ($http) {
this.Users = '';
this.errors = '';
this.SearchEmployee = function () {
// Ajax call
$http({
method: 'GET',
url: '/Home/GetEmployeeList',
params: { filterData: 'Test' },
headers: { 'Content-Type': 'application/x-www-form-urlencoded' }
}).then(onSuccess, onError);
var onSuccess = function (response) {
this.userUsers = response.data;
this.errors = '';
};
var onError = function (reason) {
this.userUsers = reason;
this.errors = "Error in retrieving data.";
};
return this.Users;
}
}]);
angular.module('Employee', ['EmployeeServiceModule'])
.controller('EmployeeController', ['EmployeeSer', '$scope', '$http', function (EmployeeSer, $scope, $http) {
this.Id = '';
this.name = '';
this.expertise = '';
$scope.repoSortOrder = 'id';
$scope.filterField = '';
// Call to service
this.GetAllEmployee = function () {
// Initiates the AJAX call
$scope.User = EmployeeSer.SearchEmployee();
// Returns the promise - Contains result once request completes
return true;
};
this.AddEmployee = function () {
var empData = {
Id: $("#txtId").val(),
Name: $("#txtName").val(),
Expertise: $("#expertise").val()
};
$http({
method: 'POST',
url: '/Home/Create',
params: JSON.stringify(empData),
headers: { 'Content-Type': 'application/x-www-form-urlencoded' }
}).then(onSuccess, onError);
// Returns the promise - Contains result once request completes
return true;
};
var onSuccess = function (response) {
$scope.user = response.data;
$scope.error = '';
};
var onError = function (reason) {
$scope.error = "Error in retrieving data.";
};
}]);
It's because you are returning the users before the data is fetched from the server. Also it doesn't seem like you are assigning them correctly.
Here are two ways to solve the problem:
Firstly. You bind your controller user-data to the user-data in the service.
angular.module('EmployeeServiceModule', [])
.service('EmployeeSer', ['$http',function ($http) {
this.Users = '';
this.errors = '';
$http({
method: 'GET',
url: '/Home/GetEmployeeList',
params: { filterData: 'Test' },
headers: { 'Content-Type': 'application/x-www-form-urlencoded' }
}).then(onSuccess, onError);
var onSuccess = function (response) {
this.Users = response.data;
this.errors = '';
};
var onError = function (reason) {
this.users = null;
this.errors = "Error in retrieving data.";
};
}
}]);
angular.module('Employee', ['EmployeeServiceModule'])
.controller('EmployeeController', ['EmployeeSer', '$scope', '$http', function (EmployeeSer, $scope, $http) {
this.users = EmployeeSer.users;
EmployeeSer.SearchEmployee();
}]);
And the second way would be to return the promise in the service and unwrap it in the controller.
angular.module('EmployeeServiceModule', [])
.service('EmployeeSer', ['$http',function ($http) {
this.SearchEmployee = function () {
return $http({
method: 'GET',
url: '/Home/GetEmployeeList',
params: { filterData: 'Test' },
headers: { 'Content-Type': 'application/x-www-form-urlencoded' }
});
}
}]);
angular.module('Employee', ['EmployeeServiceModule'])
.controller('EmployeeController', ['EmployeeSer', '$scope', '$http', function (EmployeeSer, $scope, $http) {
this.GetAllEmployee = function () {
EmployeeSer.SearchEmployee()
.then(onSuccess, onError)
};
var onSuccess = function (response) {
$scope.user = response.data;
$scope.error = '';
};
var onError = function (reason) {
$scope.error = "Error in retrieving data.";
};
}]);
OFF TOPIC
You should probably consider using ngModel instead of jQuery to get you data to the controller.
Not like this:
var empData = {
Id: $("#txtId").val(),
Name: $("#txtName").val(),
Expertise: $("#expertise").val()
};
// Here serverRequest is my service to make requests to the server
serverRequest.postReq = function(url, data, sucessCallback, errorCallback){
$http({
method: 'POST',
url: urlToBeUsed,
data:data,
headers : {'Content-Type': 'application/x-www-form-urlencoded'}})
.success(function(data, status, headers, config) {
sucessCallback(data);
})
.error(function(data, status, headers, config){
errorCallback(data);
})
}
// In the controller
serverRequest.postReq('urlToBeCalled', dataToBeSent, scope.successCb, scope.errorCb);
scope.successCb = function(data){
// functionality to be done
}
scope.errorCb = function(data){
// functionality to be done
}
Try it this way your problem might be solved
Promise must be unwrapped in your controller if you want to use it

Categories

Resources