Assign to variable after then catch [duplicate] - javascript

This question already has answers here:
How do I return the response from an asynchronous call?
(41 answers)
How to use $http promise response outside success handler
(3 answers)
Closed 5 years ago.
I have a $watchCollection in angularJS that calls the function getBalance(addr) in the listener.
$scope.$watchCollection('settings',
function() {
for (i = 0; i < $scope.settings['accounts'].length; i++) {
var bal = $scope.getBalance($scope.settings['accounts'][i]);
console.log(bal);
}
}
);
The function getBalance is defined as follows:
$scope.getBalance = function(addr) {
var balance;
if ($scope.settings.contract !== null) {
$scope.settings.contract.deployed().then(function(deployed) {
return deployed.balanceOf(addr);
}).then(function(res) {
balance = res.toNumber();
console.log(balance);
return balance;
}).catch(function(err) {
console.log(err.message);
});
}
return balance;
};
The problem is that in then, the balance variable is printed correctly however, in $watchCollection, return is undefined.
The problem should be because JS keeps executing without waiting for a result therefore the variable is read as undefined however, how do I have to change these two snippets of code in order to get the result when ready and append it to $scope.balance.

It looks like you're trying to change async code to sync code, which you can't really do. You need to carry the promise all the way through, in both.
Instead of setting balance to a variable and returning that variable, return the promise itself, then use then in your $watchCollection to get the value.
$scope.$watchCollection('settings',
function() {
for (i = 0; i < $scope.settings['accounts'].length; i++) {
$scope.getBalance($scope.settings['accounts'][i])
.then(bal => console.log(bal));
}
}
);
$scope.getBalance = function(addr) {
if ($scope.settings.contract !== null) {
return $scope.settings.contract.deployed().then(function(deployed) {
return deployed.balanceOf(addr);
}).then(function(res) {
balance = res.toNumber();
console.log(balance);
return balance;
}).catch(function(err) {
console.log(err.message);
});
}
return Promise.resolve(null);
};
Note, in functions that return Promises, make sure all pathways return a Promise or bad things will happen (hence the Promise.resolve(null)).

Related

Variable changed inside arrow function not changed when consoled outside the arrow function [duplicate]

This question already has answers here:
Why is my variable unaltered after I modify it inside of a function? - Asynchronous code reference
(7 answers)
How do I return the response from an asynchronous call?
(41 answers)
Closed 2 years ago.
I am working with angular and typescript and want to change the value of the variable inside the function. I am using a service to get the data. The code is shown below:
isValue:boolean = false;
onChangeValue(list: List) {
this.someServive.getData(list).subscribe(
item => {
if(item.value === 1) {
this.isValue = true;
}
});
console.log(this.isValue); //the value is still false here
}
Good day!
It happens due to the fact, that your service call is an async operation. And browser doesn't wait when your service emits some value, which you handle in subscription block.
isValue = false;
onChangeValue(list: List) {
this.someServive.getData(list).subscribe(item => {
if (item.value === 1) {
this.isValue = true;
this.executeOnUpdateCallback();
}
});
}
executeOnUpdateCallback() {
console.log(this.isValue); // true
}
Something like this you should do to handle it. I hope, you got it (please google about js event loop)
Since javascript is asynchronous, the value won't change until the getData service call actually happens.
In your case console executes before the getData happens.
You can either try it with promise or callback
Try below:
isValue:boolean = false;
onChangeValue(list: List) {
onDataRecieved((res)=>{
console.log(this.isValue);
});
}
onDataRecieved(cb){
this.someServive.getData(list).subscribe(
item => {
if(item.value === 1) {
this.isValue = true;
cb(true);
}
});
}

delay function return until a value is set [duplicate]

This question already has answers here:
How do I return the response from an asynchronous call?
(41 answers)
Closed 2 years ago.
i have a function , i need to delay its return until a value is set (by calling another function call_api basically i need to wait for second function result to be able to return the first function result )
here is what ti got
function getList(s, p)
{
var output = false ;
call_api(s , p , function(result){
console.log(result);
output = result;
})
while (output == false )
{
1 ;
}
return output ;
}
but it wont work while somehow is messing thing up
is there a way to solve this ?
ps : i know about promise / async function but i cant use them (its a test i ant use them in the test )
You could do it using Promises, using a callback, or by checking the value every interval, using setTimeout. You can't do otherwise by definition of the Javascript language.
Using promises:
async function getList(s, p) {
return await new Promise(resolve => call_api(s, p, result => resolve(result)));
}
Using callback:
var output = false;
call_api(s, p, result => {
output = result;
callback();
});
function callback() {
// rest of code
}
Using setTimeout:
var output = false;
call_api(s, p, result => output = result);
checkOutput();
function checkOutput() {
if (output === false) {
setTimeout(checkOutput, 100);
} else {
// rest of code
}
}

Javascript promise returns undefined in switch statement [duplicate]

This question already has answers here:
How do I return the response from an asynchronous call?
(41 answers)
Closed 4 years ago.
Sorry if this question has been solved before, I have checked this, this one, too (which, I thought, was a good lead, but I failed to understand the accepted answer) and lastly this one.
I have this case in a switch statement:
function setFieldTransformation(iteration) {
//Omitting first hundred lines and switch declaration...
case "customer.subscriptionSet":
var subscriptionCode;
if (iteration.oldValue && iteration.newValue) {
if (Array.isArray(iteration.oldValue) && Array.isArray(iteration.newValue)) {
subscriptionCode = iteration.oldValue[0].service;
} else {
subscriptionCode = iteration.oldValue.service;
}
} else if (iteration.oldValue) {
if (Array.isArray(iteration.oldValue)) {
subscriptionCode = iteration.oldValue[0].service;
} else {
subscriptionCode = iteration.oldValue.service;
}
} else {
if (Array.isArray(iteration.newValue)) {
subscriptionCode = iteration.newValue[0].service;
} else {
subscriptionCode = iteration.newValue.service;
}
}
return getSubscriptionName(subscriptionCode);
break;
}
What I'm trying to achieve:
Here I check for a subscription code, then I call this function:
function getSubscriptionName(subscriptionCode) {
ServiceService.getService(subscriptionCode)
.then(function(response){
var subscriptionName = response.data.name
return response.data.name;
})
}
Which calls a service to get the subscription name. That string is then passed through this function and printed in a table:
function transformDetailValuesReworked(iteration) {
//...
var fieldSetTransformation = setFieldTransformation(iteration);
return fieldSetTransformation;
}
What actually happens:
If I understand correctly the asynchronous nature of the promises, var subscriptionName = response.data.name could never happen, so the return is undefined.
What I have tried:
I have tried a chained promise approach, but it does not behave the way I expect. Also, and even though it is not a good practice, I've tried to set up callbacks in the functions, but ultimately ending up in the same dead spot.
I'm pretty sure I can use an async function approach, but I'm concerned about compatibility issues.
Could you shed some light? Thank you.
You've simply forgotten to return anything from getSubscriptionName
function getSubscriptionName(subscriptionCode) {
return ServiceService.getService(subscriptionCode)
.then(function(response){
var subscriptionName = response.data.name
return response.data.name;
})
}
But then your next method needs to treat it as async too
function transformDetailValuesReworked(iteration) {
//...
var fieldSetTransformation = setFieldTransformation(iteration);
return fieldSetTransformation; // This is a promise not a value!
}

How can I access a variable inside a .then function which is inside another .then function? [duplicate]

This question already has answers here:
JavaScript closure inside loops – simple practical example
(44 answers)
Closed 5 years ago.
Here I'm trying to Log value of a to console.
driver.sleep(2000).then(function logAInConsole() {
var a = ["Quas","Wex","Exort","Invoke"];
for(var i = 0; i < a.length; i++) {
driver.sleep(1000).then(function loggingA() {
driver.sleep(1000).then(function() {
console.log(a[i]);
})
});
}
});
Result of given code is:
Undefined
Undefined
Undefined
Undefined
You shouldn't create function inside the loop - use "forEach" instead: ("driver" object created to simulate real promise behavior)
var driver = {}
driver.sleep = function() {
return new Promise((resolve)=>{
resolve()
})
}
driver.sleep(2000).then(function(){
var a = ["Quas","Wex","Exort","Invoke"];
a.forEach((b)=>{
driver.sleep(1000).then(function loggingA(){
driver.sleep(1000).then(function(){
console.log(b);})
});
})
});
It can access the function. That the reason it generate "undefined" rather than an error when accessing a[i].
The bug of the code is, when accessing variable i, it was incremented already 4. As a result, a[4] is undefined.
The problem is that, because driver.sleep is a promise, it runs after i has been incremented past the length of a. That is, by the time the promises run, i is 4, which is not a valid index in a. You can get around this by doing one of two things (adding a driver mock as well):
1: Bind i to the outermost function inside of the for loop:
var driver = {
sleep: function(time) {
return new Promise(function(resolve, reject) {
setTimeout(resolve, time);
});
}
}
driver.sleep(2000).then(function logAInConsole() {
var a = ["Quas","Wex","Exort","Invoke"];
for(var i = 0; i < a.length; i++) {
driver.sleep(1000).then(function loggingA(i) {
driver.sleep(1000).then(function() {
console.log(a[i]);
})
}.bind(this, i));
}
});
2: Use forEach:
var driver = {
sleep: function(time) {
return new Promise(function(resolve, reject) {
setTimeout(resolve, time);
});
}
}
driver.sleep(2000).then(function logAInConsole() {
var a = ["Quas","Wex","Exort","Invoke"];
a.forEach(function(value) {
driver.sleep(1000).then(function loggingA(i) {
driver.sleep(1000).then(function() {
console.log(value);
})
});
});
});
In general, if you don't need to change anything in a, it makes more sense to use forEach, since it's generally more clear than a for loop at the cost of a tiny bit of performance. If you absolutely need a and i for some reason, or if you need the looping to be lazy, the only way to ensure that they are available in the promise functions is to bind them to the outermost function, preserving their value.

How to change a global variable from the inside of a anonymous function? [duplicate]

This question already has answers here:
How do I return the response from an asynchronous call?
(41 answers)
Closed 8 years ago.
I have the following function:
var checkExist = function(_id) {
var t;
car.count({
id: _id
}, function(err, c) {
if (c != 0) {
t = 0;
console.log(t);
} else {
t = 1;
console.log(t);
}
});
console.log(t);
return t;
}
The problem: 't' is undefined at the end of the function, but it changes values inside of the if/else block. Any suggestions how to solve this?
merci
OP you need to read something about async programming.
Long story short.
You CAN'T somehow make it to be synchronous
var checkExist = function(_id) {
/*async blah-blah-blah*/
return result;
};
if(checkExist(123)) {} //THIS WON'T work
You can make your function to take a callback
var asyncCheckExist = function(_id, success, error) {
car.count({id: _id}, function(err, result) {
if(err) return error && error(err);
success(result);
});
};
asyncCheckExist(123, function(exists) {
if(exists) {} //THIS WILL Work
});
Anyway you should google for async programming, callbacks, callback hell, promises etc.

Categories

Resources