In angular js application how to make other codes wait until some code are done? - angularjs

In angular js application, if have to send a request to the database, and until response comes no other actions should be done, Now I am not able to do that
function checkStep() {
if (currenctStep == 1 && checkBalance()) { // request database to check balance
alert('balance is not enough');
} else if (currentStep == 2) {
goToNextStep();
} else if (currentStep == 3) {
validateAll();
}
// ... some actions should wait until above codes are executed,
// here some codes that do some actions and should change current step after
// checkBalance() respose comes
}
What can I do in order to make all other codes wait until the response comes in checkBalance()

checkBalance is a async call, ti should return a promise.
Something like:
function checkStep() {
if (currenctStep == 1) { // request database to check balance
checkBalance().then(function (response) {
// parse response data
if (currentStep == 2) {
goToNextStep();
} else if (currentStep == 3) {
validateAll();
}
}, function (error) {
// failed to call DB
});
}
// ... some actions
}
where checkBalance can be:
function checkBalance() {
// some call DB here
return $http({method: 'GET', url:URL}).then(function (result) {
return result;
}, function (error) {
console.error(error);
return $q.reject(error);
});
};

Related

How can I save a value in this React lambda function?

I have this React project template, it uses Spring for backend and a PostgreSQL database.
Here, I have the name of a caregiver, and what i want, is to get the id of that caregiver.
I don't know how to retrieve the id, from the findCaregiver method. When in the function, "result.id" will show the correct id, but when it returns to "handleSubmit", the initial method, the value is gone. I tried storing it in the current components' state, in a global variable, even in localStorage. But nothing works, after the function is done, the value is gone. Any ideas? Thank you!!
handleSubmit() {
let name = this.state.formControls.caregiverName.value;
let c = this.findCaregiver(name);
console.log("id: " + c);
findCaregiver(name) {
return API_USERS.getCaregiverByName(name, (result, status, error) => {
if (result !== null && (status === 200 || status === 201)) {
console.log("Successfully found caregiver with id: " + result.id);
//result.id shows correct id here!
} else {
this.setState(({
errorStatus: status,
error: error
}));
}
});
}
getCaregiverByName is asynchronous. When you call it, the gears are set in motion, but then the function finishes immediately. Then you return to handleSubmit, and log out nothing, because it isn't done yet.
Some time later, the get finishes, and the callback function will be called. Any code that you need to run when the result is ready needs to be done in that callback, or something called by that callback.
So if we're sticking with callbacks, you can add a callback to findCaregiver:
handleSubmit() {
let name = this.state.formControls.caregiverName.value;
this.findCaregiver(name, (id) => {
console.log("id: " + id);
});
}
findCaregiver(name, callback) {
API_USERS.getCaregiverByName(name, (result, status, error) => {
if (result !== null && (status === 200 || status === 201)) {
callback(result.id);
}
}
}
If you perfer promises to callbacks (most people do), you can instead change your code to return a promise. Perhaps getCaregiverByName could be modified to return a promise, but if you don't have access to that code you can wrap your existing code in a promise like this:
handleSubmit() {
let name = this.state.formControls.caregiverName.value;
this.findCaregiver(name)
.then((c) => {
console.log("id: " + c);
});
}
findCaregiver(name) {
return new Promise((resolve, reject) => {
API_USERS.getCaregiverByName(name, (result, status, error) => {
if (result !== null && (status === 200 || status === 201)) {
resolve(result.id);
} else {
reject(error);
}
})
});
}
And if it's returning a promise, you have the option to use async/await:
asycn handleSubmit() {
let name = this.state.formControls.caregiverName.value;
const c = await this.findCaregiver(name);
console.log("id: " + c);
}

PromiseKit - Optional promise with reload first promise

I read all documentation but I don't response my question with successfull.
I have this scenario
I call the authenticated api point
If the response is 200 to 299 I fullfill
If the response is 401 I call the api for refresh the token
If i refreshed the API token I need to re-call the first api point (for recovery the needed data).
Can you help me with this problem?
Thanks
Use recursion for you needs. Using PromiseKit you can do awesome things. See my flow with refresh token request below. I expect that the code below is self-documented.
// Define here your errors
enum MyErrors: Swift.Error {
case unauthorized
case unknown
}
// Here is your primary function for retrieving remote data
func fetchRemoteData() {
self.primaryRequest()
.then { data in
return self.parsePrimaryRequest(response: data)
}
.done { parsedResult in
// do something here if all chaining is success
}
.recover { primaryRequestError in // this is your case for refresh token
if case MyErrors.unauthorized = primaryRequestError { // if not authorized
self.refreshTokenRequest()
.then { data in
return self.parseRefreshToken(data: data)
}
.done { token in
// do someting with token, save it in secure store (keychain)
self.fetchRemoteData()
}
.catch { refreshTokenError in
// refresh token request has failed
}
}
else {
throw primaryRequestError
}
}
.catch { primaryRequestError in
// here if error during request
}
}
func primaryRequest() -> Promise<Data> {
return Promise { seal in
// here you execure the request
// ...
// ...
let responseData = Data() // here you get data from URLSessionTask etc
let yourRequestStatusCode = 401 // take status code
let successCodes = Array(200...299) // define success codes
let authorizationErrorCode = 401 // define status code which requires performing refresh token request
if successCodes.contains(yourRequestStatusCode) {
return seal.fulfill(responseData)
} else if yourRequestStatusCode == authorizationErrorCode {
throw MyErrors.unauthorized
} else {
throw MyErrors.unknown
}
}
}
func parsePrimaryRequest(response: Data) -> Promise<String> {
return Promise { seal in
// here you parse response
// ...
// ...
let parsedObject = "Awesome result"
seal.fulfill(parsedObject)
}
}
func refreshTokenRequest() -> Promise<Data> {
return Promise { seal in
// here you execure the request to refresh token
// ...
// ...
let responseData = Data() // here you get data from URLSessionTask etc
let yourRequestStatusCode = 401 // take status code
let successCodes = Array(200...299) // define success codes for refresh token request
if successCodes.contains(yourRequestStatusCode) {
return seal.fulfill(responseData)
} else {
throw MyErrors.unknown
}
}
}
func parseRefreshToken(data: Data) -> Promise<String> {
return Promise { seal in
// here you parse response
// ...
// ...
let parsedObject = "00000000-00000000-00000000-00000000"
seal.fulfill(parsedObject)
}
}

Call multiple web api using Angular js one by one

I have a scenario in which there is 8 web api's called as :
#1
Sync Local DB from server DB (response will RETURN a List=> myList)
If (myList.Length > 0)
#1.1 Call web Api to Insert/Update Local DB
#2
Sync Server DB from Local DB (Request goes with a List=> myList)
If (myList.Length > 0)
#2.1 Call web Api to Insert/Update in Server DB (Response will RETURN a List=> newList)
If(newList.length > 0)
#2.2 Call web Api to Insert/Update in Local DB
I have two separate process For Head and Head Collection tables which synced with above process. So there is #3 and #4 scenario is also present.
I have call web api in the following manner...
syncHeadDataLogic();
syncHeadCollectionDataLogic();
I need that Head data should be synced first then HeadCollection data synced. But if there is no updated record for head then Head collection executed.
In my scenario my web apis called in any order but i need a order as I have described above. Kindly suggest me how I achieved this.
#Updated
//Sync Head
$scope.initializeController = function () {
if ($scope.online) {
//debugger;
syncHeadDataLogic();
syncHeadCollectionDataLogic();
}
};
function syncHeadDataLogic() {
HeadService.HeadSyncLocalDB(parseInt(localStorage.headRevision, 10), $scope.completeds, $scope.erroe);
};
$scope.SynServerDBCompleted = function (response) {
debugger;
$scope.HeadListForSync = response.HeadList;
var tempHeadCurrencyDetail = [];
if ($scope.HeadListForSync.length > 0) {
angular.forEach($scope.HeadListForSync, function (xx) {
xx.CurrencyId = xx.CurrencyServerId;
xx.Id = xx.HeadServerId;
angular.forEach(xx.HeadCurrencyDetail, function (yy) {
yy.CurrencyId = yy.CurrencyServerId;
yy.HeadId = xx.HeadServerId;
if (yy.Revision == -1)
tempHeadCurrencyDetail.push(yy);
});
xx.HeadCurrencyDetail = tempHeadCurrencyDetail;
});
var postData = { Revision: parseInt(localStorage.headRevision, 10), HeadList: $scope.HeadListForSync };
HeadService.SynServerDB(postData, $scope.completed, $scope.erroe);
}
else {
// alertsService.RenderSuccessMessage("There is no change in data after your last synchronization.");
}
};
$scope.requestErrorwer = function (response) {
debugger;
};
$scope.completed = function (response) {
debugger;
if (response.RevisionNo == localStorage.headRevision) {
syncHeadCollectionDataLogic();
// alertsService.RenderErrorMessage("There is newer version on the server. Please Sync from server first.", "MessageAlert");
}
else {
syncData(response);
}
};
$scope.completeds = function (response) {
debugger;
if (response.RevisionNo == localStorage.headRevision) {
syncHeadCollectionDataLogic();
// alertsService.RenderSuccessMessage("You are already working on the latest version", "MessageAlert");
}
else {
syncData(response);
}
//
var request = new Object();
HeadService.getAllHeadForRevision(request, $scope.SynServerDBCompleted, $scope.requestErrorwer);
};
$scope.erroe = function (response) {
debugger;
// alertsService.RenderErrorMessage("Data Synchronization Failed", "MessageAlert");
};
function syncData(data) {
debugger;
$scope.ReturnedRevisonNo = data.RevisionNo;
if (data.HeadList && data.HeadList.length > 0) {
var postData = { Revision: $scope.ReturnedRevisonNo, HeadList: data.HeadList, HeadRevision: $scope.ReturnedRevisonNo };
HeadService.AddUpdateHeadAfterSync(postData, $scope.cmpSync, $scope.Error);
}
else {
syncHeadCollectionDataLogic();
}
};
$scope.cmpSync = function (response) {
debugger;
localStorage.headRevision = $scope.ReturnedRevisonNo;;
alertsService.RenderSuccessMessage("The synchronization has been completed successfully.");
syncHeadCollectionDataLogic();
};
$scope.Error = function (response) {
debugger;
// alertsService.RenderErrorMessage(response.ReturnMessage);
// alertsService.SetValidationErrors($scope, response.ValidationErrors);
};
////////////Sync End
//Sync Head Collection
function syncHeadCollectionDataLogic() {
HeadService.HeadSyncLocalCollectionDB(parseInt(localStorage.headCollectionRevision, 10), $scope.completedCollections, $scope.erroeCollection);
};
$scope.SynServerDBCompletedCollection = function (response) {
$scope.HeadCollectionListForSync = response.HeadCollectionList;
if ($scope.HeadCollectionListForSync.length > 0) {
angular.forEach($scope.HeadCollectionListForSync, function (value, index) {
value.Id = value.HeadCollectionServerId;
angular.forEach(value.HeadCollectionDetails, function (v) {
v.CommittedCurrencyId = v.CommittedCurrencyServerId;
v.HeadId = v.HeadServerId;
v.WeightId = v.WeightServerId;
v.HeadCollectionId = value.HeadCollectionServerId; //change
angular.forEach(v.HeadCollectionAmountDetails, function (xx) {
xx.CurrencyId = xx.CurrencyServerId;
});
});
});
var postData = { Revision: parseInt(localStorage.headCollectionRevision, 10), HeadCollectionList: $scope.HeadCollectionListForSync };
HeadService.SynServerCollectionDB(postData, $scope.completedCollection, $scope.erroeCollection);
}
else {
// alertsService.RenderSuccessMessage("There is no change in data after your last synchronization.");
}
};
$scope.requestErrorwerCollection = function (response) {
};
$scope.completedCollection = function (response) {
if (response.RevisionNo == localStorage.headCollectionRevision) {
// alertsService.RenderErrorMessage("There is newer version on the server. Please Sync from server first.", "MessageAlert");
}
else {
syncDataCollection(response);
}
};
$scope.completedCollections = function (response) {
if (response.RevisionNo == localStorage.headCollectionRevision) {
// alertsService.RenderSuccessMessage("You are already working on the latest version", "MessageAlert");
}
else {
syncDataCollection(response);
}
var request = new Object();
HeadService.getAllHeadCollectionForRevision(request, $scope.SynServerDBCompletedCollection, $scope.requestErrorwerCollection);
};
$scope.erroeCollection = function (response) {
// alertsService.RenderErrorMessage("Data Synchronization Failed", "MessageAlert");
};
function syncDataCollection(data) {
$scope.ReturnedRevisonNo = data.RevisionNo;
if (data.HeadCollectionList && data.HeadCollectionList.length > 0) {
var postData = { Revision: $scope.ReturnedRevisonNo, HeadCollectionList: data.HeadCollectionList, HeadRevision: $scope.ReturnedRevisonNo };
HeadService.AddUpdateaHeadCollectionAfterSync(postData, $scope.cmpSyncCollection, $scope.ErrorCollection);
}
};
$scope.cmpSyncCollection = function (response) {
localStorage.headCollectionRevision = $scope.ReturnedRevisonNo;;
alertsService.RenderSuccessMessage("The synchronization has been completed successfully.");
$scope.initializeController();
};
$scope.ErrorCollection = function (response) {
// alertsService.RenderErrorMessage(response.ReturnMessage);
// alertsService.SetValidationErrors($scope, response.ValidationErrors);
}
//End
I need that Head data should be synced first then HeadCollection data synced. But if there is no updated record for head then Head collection executed.
What you need is chained promises. Try this (I'm giving you pseudocode for now):
HeadService.HeadData
|-----------------|
HeadCollection(headDataResult)
|------------------|
finalHandler(headCollectionResult)
|------------------|
HeadService.HeadData()
.then(HeadService.HeadCollection) // return or throw Err if headDataResult is empty
.then(finalHandler);
Here, the order of execution of the promises will be predictable, and sequential. Also, each promise will be returned the resolved value of the previous promise
AngularJS as you can see in the documentation here, uses Promises out of the box with the $http injectable. You can define a factory like so:
// Factory code
.factory("SampleFactory", function SampleFactory($http) {
var sampleFactoryObject = {};
sampleFactoryObject.getSomething = function() {
return $http.get('/someUrl');
}
sampleFactoryObject.getSomething.then(function resolveHandler(res) {
return res;
},
function rejectHandler(err) {
throw new Error(err);
});
sampleFactoryObject.getSomethingElse = function() {
return $http.get('/someOtherUrl');
}
sampleFactoryObject.getSomethingElse.then(function resolveHandler(res) {
return res;
},
function rejectHandler(err) {
throw new Error(err);
});
return sampleFactoryObject;
});
// Controller code
.controller('myController', function myController(SampleFactory) {
SampleFactory.getSomething()
.then(SampleFactory.getSomethingElse())
.then(finalHandler);
var finalHandler = function(resultOfGetSomethingElse) {
console.log(resultOfGetSomethingElse);
}
});

NodeJS callback: How to make the call wait for mongodb query result

I have a registration dialog where when the user enters username and password I need to check the DB whether the user is present
or not. But when I am validation for the same my call does not hold back until I get the results from the server.
After searching for a while I got to know about callbacks. So I have added a call back inside this.isUser method.
And it is successful. But now doRegistration method is not synchronous with the isUser method.
How to make all my calls synchronous?
this.doRegistration = function(uname, pwd, confirmPwd) {
if(this.isUser(uname)) {
return "USER_EXISTS";
} else {
saveUser(uname, pwd);
return "SUCCESS";
}
};
this.isUser = function(username) {
var users = new Array();
getAllUsers('param', function(response) {
users = response;
console.log(users.length);
for(i = 0; i < users.length; i++) {
if(users[i].username === username) {
return true;
}
}
return false;
});
};
function getAllUsers(param, callback) {
loginFactory.AllUsers.query(function(response) {
if(response != undefined && response.length > 0) {
callback(response);
}
});
}
You may rewrite the code like following:
this.doRegistration = function(uname, pwd, confirmPwd, callBack) {
this.isUser(uname,function(flag) {
if(flag){
callBack("USER_EXISTS");
}
else {
saveUser(uname, pwd, function(err,result){
if(err){
callBack("SAVING_FAILED");
}
else {
callBack("SUCCESS");
}
});
}
});
};
this.isUser = function(username,callBack) {
var users = new Array();
getAllUsers('param', function(response) {
users = response;
console.log(users.length);
for(i = 0; i < users.length; i++) {
if(users[i].username === username) {
callBack(true);
}
}
callBack(false);
});
};
function saveUser(userName, pwd, callBack){
//code to save user
//chek for error in saving
if(err){
callBack(err,null)
}
else {
callBack(null, "success")
}
}
function getAllUsers(param, callback) {
loginFactory.AllUsers.query(function(response) {
if(response != undefined && response.length > 0) {
callback(response);
}
});
}
You may also define saveUser as a function with callback. Here it wont wait for saveUser method to complete.

return bool value from middleware to express controller

I want to return a boolean value from middleware defined as
module.exports = {
authenticatepracticename: function(pname) {
ecollection.find({ $and: [{'name':pname},{'status' : 'active'}] }).exec(function (err, result) {
if (err) return false;
if(result.length == 1){
// console.log('true');
return true;
}
else{
// console.log('false');
return false;
}
});
},
// ...
}
to my express controller defined as
exports.checkcredentails = function (req, res) {
var result = practice.authenticatepracticename(practiceName);
}
but result is coming undefined even though middleware function is getting called.
The reason why you are getting undefined result from practice.authenticatepracticename is because ecollection.find performs asynchronous action and authenticatepracticename end without returning any value (which is undefined in JavaScript).
In order to improve that, you would need to provide a callback function from your checkcredentails to authenticatepracticename.
Example:
exports.checkcredentails = function (req, res) {
practice.authenticatepracticename(practiceName, function(err, result){
// you can handle error and result here e.g. by sending them back to a customer
res.send("Result: " + result);
});
}
And your authenticatepracticename:
authenticatepracticename: function(pname, cb) {
ecollection.find({ $and: [{'name':pname},{'status' : 'active'}] }).exec(function (err, result) {
if (err) return cb(err)
if(result.length == 1){
// console.log('true');
cb(null, true)
}
else {
// console.log('false');
cb(null, false)
}
});
}
I hope that will help.

Resources