Access a variable outside of a promise [duplicate] - node.js

This question already has answers here:
How do I return the response from an asynchronous call?
(41 answers)
Closed 4 years ago.
I am writing a steam bot and am trying to check, if one of the items in a trade is worth below 1 USD. I need to access the "pass" variable, but it never works. Can someone help?
var receive = offer.itemsToReceive;
var pass = true;
receive.forEach(function(id) {
var args = id.split(",");
market.getItemPrice("some app id", some item name).then(function(result) {
var json = JSON.parse(JSON.stringify(result)); // returns e.G $0.08
var price = parseFloat(json.median_price.substring(1));
if(price*100 < 100) {
pass = false;
}
});
});

This question is asked a lot, but hopefully explaining it in your own problem's terms will help you understand.
Your code should wait for any possibility of pass = false;, but it doesn't because you call a asynchronous function --- imagine the code immediately moves on after calling that. Your foreach function is immediately processed and the next line is called until .getItemPrice responds some time later.
So instead, to "wait" for all the results, you can do something like:
var receive = offer.itemsToReceive;
var pass = true;
var itemReceivePromises = receive.map(id=>{
var args = id.split(",");
return market.getItemPrice("some app id", some item name).then(function(result) {
var json = JSON.parse(JSON.stringify(result)); // returns e.G $0.08
var price = parseFloat(json.median_price.substring(1));
if(price*100 < 100) {
pass = false;
}
});
});
Promise.all(itemRecievePromises).then(results=>{
console.log('pass',pass);
});
However, you should pass the "pass" result back through the promise instead of using a higher scoped variable.

Related

Flutter : Function need to wait [duplicate]

This question already has an answer here:
How to wait for forEach to complete with asynchronous callbacks?
(1 answer)
Closed 1 year ago.
Here is my code
Future<List<Record>> getRecordElements() async {
int i=0;
String at;
var cont =0;
List<String> name= [];
var db = await FirebaseDatabase.instance.reference().child("Volunteers/"+widget.vname+"/Records");
db.once().then((DataSnapshot snapshot){
Map<dynamic, dynamic> values = snapshot.value;
print(values);
values.forEach((key,values) async {
if(values["cont"]!=null){
//Few complicated operations
values.forEach((key,values) {
print(values);
if(key=="name"){
name.add(values);
}
});
});
});
print("name " + name.toString());
//few more operations
return items;
}
I have modified out irrelevent parts of the code.
Thing is, name is an array whose values are fetched from the database. Only after the array is set, can function proceed.
But what is happening is that name is being printed before it has been set. And hence the other operations after that are also being affected.
I need the fetching to finish first, and only then move ahead.
Please help
I think You Should fetch Your data at initializing stage i.e. you should create a function to fetch data from database and then call that function from initState

I am having issues with the array in nodejs [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)
Closed 4 years ago.
Node.js code to extract all the links from the web page and store it in the variable that stores the data inside the scope of the function but not showing the data outside the scope of the function.
var ineed = require('ineed');
var url = require('get-urls');
var list = require('collections/list');
var fs = require('fs');
var arr = [];
ineed.collect.hyperlinks.from("https://energy.economictimes.indiatimes.com/rss/", function (err, response, result) {
var links = url(JSON.stringify(result)).toArray();
var str="/rss/";
for(var i = 0; i<links.length; i++){
if((links[i].search(str))>-1){
arr.push(links[i]);
}
}
console.log(arr);
// I am getting the output of the array here
})
//While printing the array I am not getting the output
console.log(arr);
You got noting in second console.log just because your code wich collect information run asynchronously and arr accepted any value after the first console.log executed. So either you rewrite your code on "clean" promises like
new Promise((resolve)=>ineed.collect.hyperlinks.from(
"https://energy.economictimes.indiatimes.com/rss/",
function (err, response, result) {
var links = url(JSON.stringify(result)).toArray();
var str="/rss/";
for(var i = 0; i<links.length; i++){
if((links[i].search(str))>-1){
arr.push(links[i]);
}
}
resolve(arr)
}
))
.then((arr)=>console.log(arr));
or convert to async/await function.

Nodejs run promises sequentially

Dears ,
How can i run promises in nodejs sequentially , in the following example am looping through array of hours then for each fetched hour get result from the database , the issue here : am getting results but i want it sequentially same order that i got hours .
angular.forEach(SharedVar.getCategories(), function (h) {
t = h.split('-', 2);
t = t[0];
RESTApi.getAnswerdCallsByHour(t).then(function (answerdTotal) {
$scope.answerdCallsTotalByHour.push(answerdTotal);
var d = SharedVar.getDataS();
d[count] = answerdTotal;
SharedVar.setDataS(d);
count++;
});
});
Thanks ,
var promise = Promise.resolve(); // make an empty promise in the way you do it with your promise library
angular.forEach(SharedVar.getCategories(), function (h) {
promise.then(function() {
return RESTApi.getAnswerdCallsByHour(t).then(function (answerdTotal) {});
});
});
The way to do it sequently would be to do one Request and do the next request inside the promise.
I think the better approach by far is to extend your SharedVar.setDataS(d) function in a way, that it does not depend on getting the data sequentially. Like having a SharedVar.setDataS(d, index) and using the config var in your $http.get (or whatever) functioncall inside your RESTApi to promote that index all the way to the promise.
If your RESTApi looks like this:
var RESTApi = {
getAnswerdCallsByHour : function(hour) {
var url = "bla.com/myservice?hour=" + hour;
return $http.get(url).data;
}
// Some other Methods...
Then you need a way to pass something to "reorder" your Data when it arrives asynchronously, this could be a index you count up or in your case maybe the hour Variable:
var RESTApi = {
getAnswerdCallsByHour : function(hour) {
var url = "bla.com/myservice?hour=" + hour;
var config = [];
config.hour = hour;
return $http.get(url, config); // Return the promise not just data or a specific field
}
// Some other Methods...
Now when your promise is fullfiled you can access your "hour" Variable like so:
var d = SharedVar.getDataS();
d[promise.config.hour] = promise.data;
SharedVar.setDataS(d);
Now you know what piece of data correlates to which request and you do not need to recieve Data in order. The last piece only works properly when hours runs sequential from 0 to 23, if that isn't the case you need to:
var RESTApi = {
getAnswerdCallsByHour : function(hour, index) {
var url = "bla.com/myservice?hour=" + hour;
var config = [];
config.index = index;
return $http.get(url, config);
}
// Some other Methods...
...
...
var d = SharedVar.getDataS();
d[promise.config.index] = promise.data;
SharedVar.setDataS(d);
Safari's answer is how I typically handle this. (Sorry, I don't have enough rep to comment yet...) You were experiencing problems with it because the example provided does not capture and use the new promise in subsequent loops. See my comments on the slightly modified version here:
var promise = Promise.resolve();
angular.forEach(SharedVar.getCategories(), function (h) {
t = h.split('-', 2);
t = t[0];
// You must capture the new promise here; the next loop will wait
// for the promise returned from getAnswerdCallsByHour to resolve.
promise = promise.then(function() {
// Halt downstream promises until this returned promises finishes
return RESTApi.getAnswerdCallsByHour(t).then(function (answerdTotal) {
$scope.answerdCallsTotalByHour.push(answerdTotal);
var d = SharedVar.getDataS();
d[count] = answerdTotal;
SharedVar.setDataS(d);
count++;
});
});
});

Node.js while loop return deffered result

What I'm trying to do is this, I have 2 users an attacker and a defender. I want the call hit() function until one of the runs out of Health, hit() should be called on turns, first attacker, then defender, then attacker and so on until one reaches 0 hp.
My idea was to do it with a while loop, with current code all I get is the console.log from hit(), an infinite loop. The data from hit() is returned correctly if it's not inside a loop ... I could simply just work in the while loop and not use the hit function but it would mean repeating a lot of code, since there will be a few things to consider before a hit actually happens.
If you have an alternative to the while loop I'm open to ideas, also I should mention I'm new at node so keep it as simple as possible please. Thank you.
This is the relevant part of the code:
var prepareAttack = function(attacker,defender) {
connectdb().done(function(connection) {
query(connection,'SELECT * FROM members WHERE name = ?', attacker).done(function(result) {
var attackerData = result[0][0]
query(connection,'SELECT * FROM members WHERE name = ?', defender).done(function(result) {
var defenderData = result[0][0]
var attackerHp = attackerData.hp
var defenderHp = defenderData.hp
while(attackerHp > 0 && defenderHp > 0) {
hit(attackerData,defenderData).done(function(result){
defenderHp = result;
console.log(defenderHp)
})
hit(defenderData, attackerData).done(function(result) {
attackerHp = result;
console.log(attackerHp)
})
}
})
})
})
}
var hit = function (attackerData, defenderData) { // simplified code just relevant parts inside.
console.log('hitting')
var defer = Q.defer()
var newHp = 0;
defer.resolve(newHp)
return defer.promise
}

Why I have different results for 'same' thing? [duplicate]

This question already has answers here:
How do I return the response from an asynchronous call?
(41 answers)
Closed 7 years ago.
I need to mention that I'm new to Node.js in general but I'm not sure why for the following code will give me different outputs in console for questions and allQuestions variable ?
var models = require('./models')(mongoose);
var query = models.Question.find({});
var questions = Array();
query.exec(function(err, allQuestions){
//catch the error;
questions = allQuestions;
console.log(allQuestions);
});
console.log(questions);
Output of questions variable will be only: Mongoose: questions.find({}) { fields: undefined } while allQuestions will contain all the questions from database.
I need to know why ?
Also I need that my question variable contains allQuestions from database.
Thats because query.exec() runs the function you passed as parameter asynchronously and the last line console.log(questions); will be executed before the callback is.
If you need the value of questions, then use another callback:
var models = require('./models')(mongoose);
var query = models.Question.find({});
var questions = Array();
query.exec(function(err, allQuestions){
//catch the error;
questions = allQuestions;
console.log(allQuestions);
done();
});
function done() {
console.log(questions);
// handle `questions` here ...
}

Resources