Service call in for loop angular js $q, promise
var FULLWEEKDAYS = [MONDAY, TUESDAY ... SATURDAY]
for (var i=0; i< FULLWEEKDAYS.length; i++) {
var reqParams = {
weekday: FULLWEEKDAYS[i],
teacherId : 97
}
TimetableService.getTeachersOccupancy(reqParams, function (data)
{
if (data) {
$scope.weeklyData.push(data);
}
}, function (err) {
//message.error('Timetable', err.data);
});
}
Serivice call is
function getTeachersOccupancy(data, successFunction, errorFunction) {
var params = $.param(data);
AjaxHandlerFactory.AjaxGet(BASETIMETABLEPATH + 'occupancy?' +
params, {}, function (response) {
successFunction(response.data);
}, function (error) {
errorFunction(error);
});
}
Question:
$scope.weeklyData.length = 0 outside for loop. Why and how to handle this in promises?
Serivce call
function getTeachersOccupancy(data, successFunction, errorFunction) {
// /SchoolAdminWS/services/schools/{schoolCd}/timeTable/occupancy?classroomId={classroomId}&date={YYYY-MM-DD}
var params = $.param(data);
***var deferred = $q.defer();***
AjaxHandlerFactory.AjaxGet(BASETIMETABLEPATH + 'occupancy?' + params, {}, function (response) {
successFunction(response.data);
***deferred.resolve(response.data);***
}, function (error) {
errorFunction(error);
***deferred.reject(error);***
});
***return deferred.promise;***
}
While calling above service, create a variable promise=[]; push all repsonses from service call, and resolve them.
var promises = [];
for (var i=0; i< FULLWEEKDAYS.length; i++) {
var reqParams = {
weekday: FULLWEEKDAYS[i],
teacherId : vm.employeeProfileId
}
var promise = TimetableService.getTeachersOccupancy(reqParams, function () {}, function () {});
promises.push(promise);
}
Now resolve using $q.all()
$q.all(promises).then(function(value) {
vm.weeklyData = value;
console.log(vm.weeklyData);
setTeacherOccupancyData(value);
vm.isSearch = true;
}, function (reason) {
console.log("Promise Rejected:" + reason);
});
Related
During loading of the partial Html with controller, my function named $scope.actionViewVisitors() is recognized and runs without errors. But whenever I use it inside another function on the same controller, it gives me an error:
TypeError: $scope.actionViewVisitors is not a function. Please see my code below:
angular.module("Visitor.controller", [])
// ============== Controllers
.controller("viewVisitorController", function ($scope, $rootScope, $http, viewVisitorService, viewAccountService, DTOptionsBuilder) {
$scope.visitorList = null;
$scope.viewAccountDetail = null;
$scope.avatar = null;
$scope.visitorDetail = null;
$scope.visitorBtn = "Create";
$scope.actionViewAccount = function () {
$scope.actionViewAccount = viewAccountService.serviceViewAccount()
.then(function (response) {
$scope.viewAccountDetail = response.data.account;
$scope.avatar = "../../avatars/" + response.data.account.AccountId + ".jpg";
})
}
$scope.dtOptions = DTOptionsBuilder.newOptions()
.withDisplayLength(10)
.withOption('bLengthChange', false);
// THIS ONE IS NOT RECOGNIZED
$scope.actionViewVisitors = function () {
$scope.actionViewVisitors = viewVisitorService.serviceViewVisitors()
.then(function (response) {
debugger;
$scope.visitorList = response.data.visitorList;
});
}
// I DON'T GET ANY ERROR HERE
$scope.actionViewVisitors();
$scope.actionViewAccount();
$scope.createVisitor = function () {
$scope.statusMessage = null;
if ($scope.visitorBtn == "Create") {
$scope.createVisitor = viewVisitorService.serviceCreateVisitor($scope.visitorDetail)
.then(function (response) {
if (response.data.response == '1') {
bootbox.alert({
message: "Successfully created a new visitor.",
size: 'small',
classname: 'bb-alternate-modal'
});
} else if (response.data.response == '0') {
bootbox.alert({
message: "Failed in creting visitor.",
size: 'small',
classname: 'bb-alternate-modal'
});
}
});
debugger;
$scope.visitorDetail = undefined;
// I GET THE ERROR WHEN I CALL THIS METHOD
$scope.actionViewVisitors();
}
}
})
// ============== Factories
.factory("viewVisitorService", ["$http", function ($http) {
var fac = {};
fac.serviceViewVisitors = function () {
return $http({
url: '/Visitor/ViewVisitors',
method: 'get'
});
}
fac.serviceCreateVisitor = function(visitor) {
return $http({
url: '/Visitor/CreateVisitor',
data: { visitor: visitor },
method: 'post'
});
}
return fac;
}])
You are overwriting the function with Promise in the following line, thus the error is correct
$scope.actionViewVisitors = function () {
$scope.actionViewVisitors = viewVisitorService.serviceViewVisitors()
.then(function (response) {
$scope.visitorList = response.data.visitorList;
});
}
Remove $scope.actionViewVisitors =
$scope.actionViewVisitors = function () {
viewVisitorService.serviceViewVisitors()
.then(function (response) {
$scope.visitorList = response.data.visitorList;
});
}
On the first call to the function you are changing it from a function to a Promise. Maybe you want to be returning the result instead?
$scope.actionViewVisitors = function () {
return viewVisitorService.serviceViewVisitors()
.then(function (response) {
debugger;
$scope.visitorList = response.data.visitorList;
});
}
I have the following promise that works perfectly:
self.getAll = function (callback) {
var users= [];
var promises = [];
$.ajax({
url: "/API/Users",
type: "GET",
success: function (results) {
var mappedContacts = $.map(results, function (item) {
promises.push($.ajax({
url: "/API/Users/contacts/" + item.id,
type: "GET"
}).then(function (contacts) {
users.push(new User(item, contacts));
}));
});
$.when.apply($, promises).then(function () {
callback(users);
});
}
});
}
I'm trying to add a second AJAX request but it's not working properly:
self.getAll = function (callback) {
var users= [];
var promises = [];
$.ajax({
url: "/API/Users",
type: "GET",
success: function (results) {
var mappedContacts = $.map(results, function (item) {
promises.push($.ajax({
url: "/API/Users/contacts/" + item.id,
type: "GET"
}).then(function (contacts) {
users.push(new User(item, contacts));
}));
});
var mappedContacts2 = $.map(results, function (item) {
promises.push($.ajax({
url: "/API/Users/contacts2/" + item.id,
type: "GET"
}).then(function (contacts2) {
users.push(new User(item, "",contacts2));
}));
});
$.when.apply($, promises).then(function () {
callback(users);
});
}
});
}
contacts2 is always empty, what am I doing wrong?
This is the User object:
var User= function (data, contacts, contacts2) {
this.id = ko.observable(data.id);
this.name = ko.observable(data.name);
this.contacts = ko.observableArray(contacts);
this.contacts2 = ko.observableArray(contacts2 );
}
Since you need both sets of contacts for each user to pass to new User() use one map() that returns a $.when() for both contacts requests. Create the user in then() of that $.when()
Something like:
self.getAll = function(callback) {
var users = [];
// return this promise ..... see notes below
return $.getJSON("/API/Users").then(results) {
// map array of promises to pass to final $.when
var promises = $.map(results, function(item) {
var req1 = $.getJSON("/API/Users/contacts/" + item.id);
var req2 = $.getJSON("/API/Users/contacts2/" + item.id);
// return this promise to mapped array
return $.when(req1, req2).then(function(contacts1, contacts2) {
// create user now that we have both sets of contacts
users.push(new User(item, contacts1, contacts2));
});
})
// should return this promise .... see notes below
return $.when.apply($, promises).then(function() {
callback(users);
// return `users` ...see notes below
});
})
}
Using a callback is an outdated approach when you could just return the promise chain shown in comments above and do :
self.getAll().then(function(users) {
// do something with users
})
i'm developing an app that received from a server a JSON array and divided data in a specific way, i've a portion of code that works if i use it alone but if i tried to insert it in an application it doesn't work.
This is my code:
ionicApp.controller('DefaultController', DefaultController)
.factory('dataService', dataService);
DefaultController.$inject = ['dataService', '$http'];
function DefaultController(dataService, $http) {
var vm = this;
console.log("Dentro ctrl");
getEvents();
function getEvents() {
console.log("Dentro getEvents");
return dataService.getEvents()
.then(function (data) {
console.log("data: " + data);
vm.data = data;
console.log("vm.data: " + vm.data);
return vm.data;
});
}
vm.submit = function (){
console.log("funzione");
console.log(vm.form);
var data = vm.form; // IMPORTANT
//console.clear();
var link = 'http://localhost/<path>/api/apiDoFix.php';
var mail = window.localStorage.getItem("mail");
var scelta = window.localStorage.getItem("scelta");
console.log(data);
console.log ("EMAIL" + mail);
console.log ("SCELTA" + scelta);
$http.post(link, {giorno: data.giorno, ora: data.ora, mail: mail, scelta: scelta})
.then(function (res){
console.log("Dentro http.post");
var response = res.data;
if (response != 'F'){
console.log("Dentro if");
console.log(response);
//window.location.href ="/#/main";
} else {
console.log("Dentro else");
}
});
};
}
dataService.$inject = ['$http'];
function dataService($http) {
console.log("qua");
var service = {
getEvents: getEvents
};
return service;
function getEvents() {
console.log("qua2");
var config = {
transformResponse: function (data, headers) {
var result = {
events: [],
schedules: []
};
var events = JSON.parse(data);
var dates = [];
console.log("qua3");
for (var i = 0; i < events.length; i++) {
if (dates.indexOf(events[i].day) === -1) {
var date = events[i].day;
dates.push(date);
result.events.push({
date: date
});
}
result.schedules.push({
date: events[i].day,
time: events[i].time
});
}
console.log("result: " + result);
return result;
}
};
return $http.get('http://localhost/ShuttleFIX/api/apiTimes.php', config)
.then(getEventsCompleted)
.catch(getEventsFailed);
function getEventsCompleted(response) {
console.log("response " + response.data);
return response.data;
}
function getEventsFailed(error) {
console.error(error);
}
}
}
is it possible to rewrite this code in a controller function without using factory?
Thank's
I am trying to write a function of mine using Bluebird promise Library.
I promisified the ldap-js the createClient function of ldap-js by:
var Promise= require('bluebird'); //done at the beginning
var createClientAsync = Promise.promisify(require('ldapjs').createClient);
getUser:function(user) {
var memberRoles = [];
var searchFilter = '(&(member='+user.dn+'))';
var opts = {
filter: searchFilter,
scope: 'sub',
attributes: ['dn']
};
createClientAsync({
url: 'ldap://x.x.x.x:3889'
})
.then(function(client){
return client.search('o=pic', opts);
})
.then(function(res) {
res.on('searchEntry', function(entry) {
console.log('entry: ' + JSON.stringify(entry.object));
for (var role in roles) {
var mapping = roles[role];
if (mapping.group === entry.object.dn) {
memberRoles.push(role);
}
}
});
})
.then(function() {
return memberRoles;
});
}
I get an error at createClientAsync undefined is not a function.
After a brief reading of the ldapjs documentation, I can suggest the following code
getUser:function(user) {
var searchFilter = '(&(member='+user.dn+'))';
var opts = {
filter: searchFilter,
scope: 'sub',
attributes: ['dn']
};
return createClientAsync({
url: 'ldap://x.x.x.x:3889'
})
.then(function(client){
return client.search('o=pic', opts);
})
.then(function(res) {
var memberRoles = [];
return new Promise(function(resolve, reject) {
res.on('searchEntry', function(entry) {
console.log('entry: ' + JSON.stringify(entry.object));
for (var role in roles) {
var mapping = roles[role];
if (mapping.group === entry.object.dn) {
memberRoles.push(role);
}
}
});
res.on('end', function() {
resolve(memberRoles);
});
});
});
}
note the "new Promise" and res.on('end' to resolve the promise once the "search" has completed
as I said, brief reading of documentation, so this may be completely invalid :p
It is possible to have a dynamic file resource?
This is my factory
factory('fileResourcedc', function ($resource) {
var FileResourcedc = $resource(
'xml/file.json',{},
{
get:{method:'GET', isArray:false}
}
);
return FileResourcedc;
})
And I am calling it from here:
var deferred = $q.defer();
var successFn = function (result) {
if (angular.equals(result, [])) {
deferred.reject("Failed because empty : " + result.message);
}
else {
deferred.resolve(result);
}
};
var failFn = function (result) {
deferred.reject("Failed dataconfResponse");
};
fileResourcedc.get(successFn, failFn);
return deferred.promise;
Note that in my factory, the filename is hard coded:
'xml/file.json'
What I need is to create a filename parameter and pass it to factory service. Is it possible?
Thaks in advance
This was my solution:
factory('fileResourcedc', function ($resource) {
var FileResourcedc = $resource(
'xml/:myFile',
{},
{
get:{method:'GET', params:{myFile:""}, isArray:false}
}
);
FileResourcedc.prototype.getCatalogue = function (fileName, successCat, failCat) {
return FileResourcedc.get({myFile:fileName}, successCat, failCat);
};
return new FileResourcedc;
})
Call:
var deferred = $q.defer();
var successFn = function (result) {
if (angular.equals(result, {})) {
deferred.reject("No catalogue");
}
else {
deferred.resolve(result);
}
};
var failFn = function (result) {
deferred.reject("Failed catalogue");
};
fileResourcedc.getCatalogue("catalogues.json",successFn, failFn);
return deferred.promise;
Thanks!