how to call a function after a function in angular - javascript

Here is my two function i want execute the GetAllSLUDetails() at first and then get broadcase value from the controllerTa. So could you help me
//==============call the state function after changed Country Name // get broadcase value from the controllerTa=================
$scope.$on('evtTACountryCodeSelect', function (event, args) {
$scope.message = args.message;
var taCountryCode = $scope.message.split(",")[0];
var taStateCode = $scope.message.split(",")[1];
alert(taCountryCode);
alert(taStateCode);
GetAllSLUDetails(taCountryCode);
alert(taStateCode);
if (taStateCode != "") {
document.getElementById("ddlState").value = taStateCode;
}
});
//================To Get All Records ======================
function GetAllSLUDetails(CountryCode) {
// alert('ctrl State' + CountryCode);
var Data = stateService.getSLU(CountryCode);
Data.then(function (d) {
$scope.StateListUpdate = d.data;
//alert(d.data);
alert(JSON.stringify(d));
}, function () {
alert('Error');
});
}

Please explain better what you are trying to do, but generally you can achieve executing a function after another using callbacks or promises.
So if you want to execute something after the GetAllSLUDetails you can either:
$scope.$on('evtTACountryCodeSelect', function (event, args) {
GetAllSLUDetails(taCountryCode, function() { // THIS
// Do whatever
});
});
function GetAllSLUDetails(CountryCode, callback) {
// alert('ctrl State' + CountryCode);
var Data = stateService.getSLU(CountryCode);
Data.then(function (d) {
$scope.StateListUpdate = d.data;
//alert(d.data);
alert(JSON.stringify(d));
callback(); // THIS
}, function () {
alert('Error');
});
}
or using Promise:
$scope.$on('evtTACountryCodeSelect', function (event, args) {
GetAllSLUDetails(taCountryCode).then(function() { // THIS
// Do whatever
});
});
function GetAllSLUDetails(CountryCode) {
return new Promise(function(resolve, reject) { // THIS
// alert('ctrl State' + CountryCode);
var Data = stateService.getSLU(CountryCode);
Data.then(function (d) {
$scope.StateListUpdate = d.data;
//alert(d.data);
alert(JSON.stringify(d));
resolve(d); // THIS
}, function (error) {
alert('Error');
reject(error); // THIS
});
});
}

Related

Function is not recognized by another function in angularjs

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;
});
}

Service call in for loop angular js $q, promise

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);
});

How promise works with nested function calls

I have a piece of code which deals with user's data. There are bunch of nested function calls :
f1(){
f2(){
....
fn{
///
}
}
}
fn accesses a database which means it's asynchronous, so I wrote it somehow that it returns a promise and in fn-1 (the function which calls fn) , we use .then() to wait for this promise. But it looks like now I have to return a promise in fn-1 and so on. Is that true ?
var keyValueExists = function(key, value) {
var query = {};
query[key] = value;
return new Promise(function(resolve, reject) {
User.count(query, function(err, count) {
if (err) {
console.log(err);
console.log('Problem with `.find` function');
reject('Problem with `.find` function');
} else {
resolve(count !== 0);
}
});
});
};
var addUser = function(newUserInfo) {
var validationResult = Common._validateUserInfo(newUserInfo);
if (validationResult.isOK) {
keyValueExists('userName', newUserInfo.userName).then(function(userNameAlreadyExists) {
if (userNameAlreadyExists) {
validationResult = {
isOK: false,
reason: 'Username already exists',
infoWithBadInput: 'userName'
}
} else {
var newUserId = generateUserId();
//TODO: change it somehting more flexible. e.g. a predefined list of attributes to iterate over
var newUser = {
'userName': newUserInfo.userName,
'password': newUserInfo.password,
'userId': newUserId,
'lastModificationTime': Common.getCurrentFormanttedTime(),
'createdTime': Common.getCurrentFormanttedTime()
};
var user = new User(newUser);
user.save(function(err) {
if (err) {
console.log(err);
console.log('There is a problem saving the user info');
} else {
console.log('A new user added: ');
console.log(newUser);
}
});
}
return validationResult;
});
} else {
return validationResult;
}
};
addUser returns undefined ! It looks like that the caller of addUser doesn't wait for it !
This is what you are effectively doing in your addUser function
var addUser = function(newUserInfo) {
var validationResult = Common._validateUserInfo(newUserInfo);
if (validationResult.isOK) {
// ... do something asynchronously without returning anything
} else {
return validationResult;
}
}
So, yeah, if validationResult.isOK, adduser WILL return undefined
Here's some code loosely based on your code, but it runs standalone to demonstrate how you possibly should be doing things
var keyValueExists = function(key, value) {
// pseudo junk, this simulates any username starting with b as existing
return new Promise(function(resolve, reject) {
resolve(value.substr(0,1) == 'b'); // barny and betty are dupes, fred and wilma are not
});
}
var addUser = function (newUserInfo) {
// var validationResult = Common._validateUserInfo(newUserInfo);
var validationResult = {isOK: !!~(['fred', 'barny'].indexOf(newUserInfo.userName)), username: newUserInfo.userName}; // dummy code
if (validationResult.isOK) {
return keyValueExists('userName', newUserInfo.userName).then(function (userNameAlreadyExists) {
if (userNameAlreadyExists) {
validationResult = {
isOK: false,
reason: 'Username already exists',
infoWithBadInput: 'userName',
username: newUserInfo.userName
}
} else {
// create new user here
validationResult.userNumber = (Math.random() * 100000000) | 0;
}
return validationResult;
});
}
else {
// this function always needs to return a promise, even if it is resolved/rejected immediately
return Promise.reject(validationResult);
}
}
addUser({userName: 'fred'}).then(function (result) {
console.log(result);
}).catch(function(err) {
console.error(err);
});
addUser({userName: 'wilma'}).then(function (result) {
console.log(result);
}).catch(function(err) {
console.error(err);
});
addUser({userName: 'barny'}).then(function (result) {
console.log(result);
}).catch(function(err) {
console.error(err);
});
addUser({userName: 'betty'}).then(function (result) {
console.log(result);
}).catch(function(err) {
console.error(err);
});

How can I get sinon to yield to multiple callbacks

I am trying to stub several ajax calls, but I want to have both beforeSend and success executed, is this possible?
I want something like this:
var stub = sinon.stub(jQuery, "ajax");
stub.onCall(0).yieldsTo("beforeSend").yieldsTo("success", {some: 'data'});
stub.onCall(1).yieldsTo("beforeSend").yieldsTo("success", {other: 'stuff'});
But this skips the 'beforeSend' method.
I know it would be easier to allow ajax to do it's stuff and use sinon's fakeServer, but I can't as I'm testing in Node with a fake browser and it just doesn't work
You could use yieldTo after the call:
var stub = sinon.stub();
stub({
foo: function() {
console.log('foo');
},
bar: function() {
console.log('bar');
}
});
stub.yieldTo('foo');
stub.yieldTo('bar');
I was able to work around this by adding some additional code:
var responses = {};
var executionComplete;
beforeEach(function () {
executionComplete = $.Deferred();
sinon.stub($, "ajax", function (options) {
if (options.beforeSend) {
options.beforeSend();
}
completeAjaxCall(options);
});
});
afterEach(function () {
$.ajax.restore();
});
var completeAjaxCall = function (options) {
var response = findResponse(options.url, options.type);
setTimeout(function () {
if (response.code < 400) {
if (options.dataFilter && response.data) {
response.data = options.dataFilter(JSON.stringify(response.data));
}
if (options.success) {
options.success(response.data);
}
} else {
if (options.error) {
options.error(response.data);
}
}
if (options.complete) {
options.complete();
}
if (response.completeExecution) {
executionComplete.resolve();
}
}, response.serverResponseTime);
};
var findResponse = function (url, type) {
var response = responses[url];
expect(response, url + ' should have a response').to.exist;
expect(response.type).to.equal(type);
delete responses[url];
if (Object.keys(responses).length === 0) {
response.completeExecution = true;
}
return response;
};
var givenResponse = function (response) {
responses[response.url] = response;
};
Then in my test I can use it like this:
it('should do some stuff', function (done) {
//given
givenResponse({serverResponseTime: 4, code: 200, url: '/saveStuff', type: 'POST'});
givenResponse({serverResponseTime: 1, code: 200, url: '/getStuff', type: 'GET'});
//when
$('button').click();
//then
executionComplete.then(function () {
expect(something).to.be.true;
done();
});
});

Serialize function with PhantomJS bridge

I have an array of links that use link parametr for function that scraped data by PhantomJS.
How to serilize this function? This for statemant runs paralely 3 function in one time and i recive an event error.
In this case its proper to use async, but how it use in series? Time of running the functions are always different, but how async should understood that it's done and start with new URL?
var phantom = require('phantom')
, async = require('async');
var urls = [
'http://en.wikipedia.org/wiki/Main_Page',
'http://es.wikipedia.org/wiki/Wikipedia:Portada',
'http://de.wikipedia.org/wiki/Wikipedia:Hauptseite'
];
async.mapSeries(urls, getTitle, function(err, result){
console.log(result);
})
function getTitle (link, callback) {
phantom.create(function(ph) {
return ph.createPage(function(page) {
return page.open(link, function(status) {
return page.evaluate((function() {
return document.title;
}), function(result) {
callback(null, result);
return ph.exit();
});
});
});
});
};
I'd try something like:
var links = []
var _ph
function init(cb) {
phantom.create(function(ph) {
//for each link in links call doStuff()
_ph = ph
doStuff(ph, link, cb)
})
}
function doStuff(ph, link, cb) {
ph.createPage(function(page) { //does things in parallel?
page.open(link, function(status) {
page.evaluate((function() {
document.title;
}), function(result) {
cb(null, result);
page.close();
});
});
}
var counter = links.length
var titles;
function results(err, res) {
titles.push(res)
if(--counter == 0) {
//done
_ph.exit()
}
}
init(results)
Probably not working code (I wrote it here), but I hope you get the idea. If you want to only use 1 page, something like:
var links = []
var _ph
var _page
function init(cb) {
phantom.create(function(ph) {
_ph = ph
ph.createPage(function(page) {
_page = page
doStuff(link, cb)
}
})
}
function doStuff(page, link, cb) {
page.open(link, function(status) {
page.evaluate((function() {
document.title;
}), function(result) {
cb(null, result);
page.close();
});
});
}
var counter = links.length
var titles;
function results(err, res) {
titles.push(res)
if(--counter == 0) {
//done
_ph.exit()
return
}
doStuff(links[counter], results)
}
init(results)

Categories