Array is empty, no data after for loop added - node.js

I'm using redis and nodejs for the first time, without success. Trying to loop insert data but got an empty array.
const redis = require("redis");
const client = redis.createClient({
retry_strategy: function(options) {
if (options.error && options.error.code === "ECONNREFUSED") {
// End reconnecting on a specific error and flush all commands with
// a individual error
return new Error("The server refused the connection");
}
if (options.total_retry_time > 1000 * 60 * 60) {
// End reconnecting after a specific timeout and flush all commands
// with a individual error
return new Error("Retry time exhausted");
}
if (options.attempt > 10) {
// End reconnecting with built in error
return undefined;
}
// reconnect after
return Math.min(options.attempt * 100, 3000);
},
});
var data_value = {
id: '235235',
totalrv: 'WAIT',
product: 'productName2',
url: 'url2',
process: 'proc',
task: 'msg'
};
client.set("key0", JSON.stringify(data_value));
client.set("key1", JSON.stringify(data_value));
client.set("key2", JSON.stringify(data_value));
client.set("key3", JSON.stringify(data_value));
client.set("key4", JSON.stringify(data_value));
//client.get("key2", redis.print);
var logger_data = {
logger: []
};
client.keys('*', function (err, keys) {
if (err) return console.log(err);
for(var i = 0, len = keys.length; i < len; i++) {
var values_v = client.get(keys[i].toString(), function(err, val) {
// console.log(logger_data);
// data is exist ...
logger_data.logger.push(JSON.parse(val));
});
}
});
// empty data
console.log(logger_data);
I wrote 2 print data result, in the loop it's working ok, but end of function, there are no data in array.

you can call a function inside the callback if you want to print the logger_data with values outside the asynchronous callback, like this
function printLoggerData(){
console.log(logger_data);
}
client.keys('*', function (err, keys) {
if (err) return console.log(err);
for(var i = 0, len = keys.length; i < len; i++) {
var values_v = client.get(keys[i].toString(), function(err, val) {
// console.log(logger_data);
// data is exist ...
logger_data.logger.push(JSON.parse(val));
// calling the function here so that it contains the latest values
printLoggerData();
});
}
});

Ok, with help of CertainPerformance, it's now working in asynchronous.
Thank you very much ...
async function getMessage () {
var logger_data = {
logger: []
};
return new Promise(function(resolve, reject) {
client.keys('*', function (err, keys) {
if (err) return console.log(err);
for(var i = 0, len = keys.length; i < len; i++) {
var values_v = client.get(keys[i].toString(), function(err, val) {
logger_data.logger.push(JSON.parse(val));
resolve(logger_data);
});
}
});
});
}
async function main() {
let message = await getMessage();
console.log(message);
}
main();

Related

Modify the value of a variable outside callback with the callback inside loop

I am new to Nodejs and I am facing with a problem: Modify the value of a variable outside callback with the callback inside a loop.
I am coding online-judgle project, this is my function to check output of a program with answer from database. I created result object to store amount of correct testcase.
function compareResult(fileName, problem, timeLimit, callback) {
const cp = require('child_process');
const exePath = 'submit\\' + fileName + '.exe';
const child = cp.spawn(exePath, ['--from=markdown', '--to=html'], {timeout: timeLimit});
MongoClient.connect(uri, function(err, db) {
if (err) throw err;
var dbo = db.db(dbName);
var query = { id_problem: problem, is_eg: "false" };
var proj = { projection: {input: 1, output: 1} };
dbo.collection("sample").find(query, proj).toArray(function(err, arr) {
if (err) throw err;
if (arr != null) {
var result = {
correct: 0,
total: arr.length
};
for (const json of arr) {
const answer = json['output'];
child.stdin.write(json['input']);
child.stdout.on('data', function(data) {
if (data == answer) {
result.correct += 1; // I want to modify result object here.
}
});
child.stdin.end();
};
console.log(result);
callback(result);
}
});
});
I want to modify result object in that place. How will I do it?
function compareResult(fileName, problem, timeLimit, callback) {
const cp = require('child_process');
const exePath = 'submit\\' + fileName + '.exe';
const child = cp.spawn(exePath, ['--from=markdown', '--to=html'], {timeout: timeLimit});
MongoClient.connect(uri, function(err, db) {
if (err) throw err;
var dbo = db.db(dbName);
var query = { id_problem: problem, is_eg: "false" };
var proj = { projection: {input: 1, output: 1} };
dbo.collection("sample").find(query, proj).toArray(function(err, arr) {
if (err) throw err;
if (arr != null) {
var result = {
correct: 0,
total: arr.length
};
for (const json of arr) {
const answer = json['output'];
child.stdin.write(json['input']);
child.stdout.on('data', function(data) {
if (data == answer) {
result.correct += 1;
}
// Decrement total here to track how many 'data' events have been emitted
result.total--;
if (result.total === 0) {
// All 'data' events have been emitted, so call the callback function
callback(result);
}
});
child.stdin.end();
};
}
});
});
}

How to get code to execute in order in node.js

I am trying to finish my script, but for some reason i don't know, it refuses to execute in the order i put it in.
I've tried placing a 'wait' function between the JoinRequest update function and the following code, but when run, it acts as if the function call and wait function were the other way round, countering the point of the wait().
const Roblox = require('noblox.js')
var fs = require('fs');
var joinRequests = []
...
function wait(ms) {
var d = new Date();
var d2 = null;
do { d2 = new Date(); }
while(d2-d < ms*1000);
};
...
function updateJReqs() {
Roblox.getJoinRequests(4745601).then((array) => {
var i;
var final = [];
for(i = 0; i < array.length; i++) {
final.push(array[i].username);
};
if(final === '') {
final = '-None';
};
joinRequests = final
console.log('Updated join requests.')
});
}
function check() {
setTimeout(() => {
fs.readFile('Request.txt',encoding = 'utf-8', function(err, data) {
if (err) {
check();
} else {
updateJReqs(); //for some reason this function is executed alongside the below, not before it.
// Tried putting wait(x) in here.
console.log('Request received: ' + data)
var solution = joinRequests
console.log('Fuffiling request with ' + solution)
fufillRequest(solution)
fs.unlink('Request.txt', function(err) {
if(err) throw err;
});
check();
}
});
}, 400)
}
check();
The script is supposed to wait until a file is created (accomplished), update the list of join requests (accomplished) and then create a new file with the list of join requests in(not accomplished).
if I understand your code you work with async code, you need to return a promise in updateJReqs and add a condition of leaving from the function because you have an infinite recursion
function updateJReqs() {
return new Promise(resolve => {
Roblox.getJoinRequests(4745601).then((array) => {
var i;
var final = [];
for(i = 0; i < array.length; i++) {
final.push(array[i].username);
};
if(final === '') {
final = '-None';
};
joinRequests = final
console.log('Updated join requests.')
resolve();
});
}
}
async function check() {
setTimeout(() => {
fs.readFile('Request.txt',encoding = 'utf-8', function(err, data) {
if (err) {
await check();
} else {
await updateJReqs();
// Tried putting wait(x) in here.
console.log('Request received: ' + data)
var solution = joinRequests
console.log('Fuffiling request with ' + solution)
fufillRequest(solution)
fs.unlink('Request.txt', function(err) {
if(err) throw err;
});
// you dont have an exit from your function check();
return 'Success';
}
});
}, 400)
}
check().then(res => console.log(res));

For loop not working properly in node js

I want to insert multiple data by for loop , but this code add 2 or 3 data only , then its continue loading loading but nothing happen ...
router.post('/addclient' , function (req , res){
var finished = false;
var user = req.body.username;
for(var i = 0 ; i <30 ; i++){
req.body.username = user + i ;
objDB.insert("clientList" ,req.body, function(err, data){
//if(err) console.log(err);
if(i>20){
finished = true;
}
});
}
if(finished){
res.redirect('/client/client-list');
}
});
you are doing it wrong. insert is asynchronous, so when insert for i=1 completes and callback gets called, maybe i is equal to 20 and more and you can't guess it. you are missing synchronous and asynchronous concepts and differences.
here is two solutions for your problem :
first, adding 30 items at once :
var clientsList = [];
for (var i = 0 ; i < 30 ; i++) {
clientsList[i] = Ith client object; // create object you want to insert for client i
}
// for example insertAtOnce is a function to insert your list
objDB.insertAtOnce(clientsList,function(err,callback) {
if (err) console.log("error : ", err);
res.redirect('/client/client-list');
});
second, using bind
function insertCallback(itr, res, err,callback) {
if (itr == 29) {
res.redirect('/client/client-list');
}
}
----
for(var i = 0 ; i <30 ; i++){
req.body.username = user + i ;
objDB.insert("clientList" ,req.body,insertCallback.bind(null, i, res);
}
Would be best if you use the async node.js library which provides control flows like running each function in series. You could use the async.whilst() method and restructure your code as:
router.post('/addclient', function(req, res) {
var user = req.body.username,
count = 0,
result = { finished = false };
async.whilst(
function () { return count < 30; },
function (callback) {
count++;
req.body.username = user + count.toString();
objDB.insert("clientList", req.body, function(err, data){
if (err) { return callback(err); }
result["data"] = data;
if( count > 20 ) result.finished = true;
callback(null, result);
});
},
function (err, result) {
if (err) { /* handle err */};
if (result.finished) res.redirect('/client/client-list');
}
);
});
You have a callback called after running insert function. It runs not exactly after running insert, and not in loop(it asynchronous). So in your code res.redirrect will never be called, because finished will be true after all loop will run. If you don't need to have all this inserts finished before answer, you can go this way:
if(i == 29){
res.redirect('/client/client-list');
}
Otherwise you need to create some queue, for example, i'm using async library https://github.com/caolan/async to create queues and running callbacks after queue ends.
router.post('/addclient', function(req, res) {
var finished = false;
var user = req.body.username;
var i = 0;
while( true ) {
if ( i > 20 ) {
res.redirect('/client/client-list');
}
req.body.username = user + i;
var promise = new Promise();
objDB.insert("clientList", req.body, function(err, data) {
promise.resolve();
});
promise.then(function() {
i++;
continue;
});
}
});
I have written it from the top of my head. But the basic idea here is that you need a loop to run infinitely, then resolve a promise; the resolution triggers continuing the loop, and increment the counter.
Use Promise. I would have done something like below
router.post('/addclient' , function (req , res){
var finished = false;
var promise = [];
var user = req.body.username;
for(var i = 0 ; i <30 ; i++) {
req.body.username = user + i;
promise.push(new Promise(resolve, reject) {
objDB.insert("clientList" ,req.body, function(err, data) {
if(err) {
reject(err)
return
}
resolve(data)
})
})
}
Promise.all(promise).then(function() {
finished = true
})
if(finished){
res.redirect('/client/client-list');
}
});

nodejs issue with undefined promise nodejs using Q

I've been wrappingmind over async and sync functions as a php developer ive never had to worry about this much. so my issue is this
i have a function
function loadPartnerInventory(args,itemIds,offers,offer) {
var deferred = Q.defer();
offers.loadPartnerInventory(args, function(err, items) {
var checkItems = [];
var len = items.length;
for(var i = 0; i < itemIds.length; i++) {
for(var j = 0; j < items.length; j++) {
if (itemIds[i] == items[j].id){
//console.log('Pushed: ' + items[j].name);
checkItems.push({
itemname: items[j].market_name,
market_hash_name: items[j].market_hash_name,
steamid: offer.steamid_other,
tradeofferid : offer.tradeofferid
});
}
}
}
deferred.resolve(checkItems);
});
return deferred.promise;
}
function loadMyInventory(args,itemIds_g,offers,offer) {
var deferred = Q.defer();
offers.loadMyInventory(args, function(err, itemsg) {
var checkItems_g = [];
var len = itemsg.length;
for(var i = 0; i < itemIds_g.length; i++) {
for(var j = 0; j < itemsg.length; j++) {
if (itemIds_g[i] == itemsg[j].id){
console.log('Pushed: ' + itemsg[j].name);
checkItems_g.push({
itemname: itemsg[j].market_name,
market_hash_name: itemsg[j].market_hash_name,
steamid: offer.steamid_other,
tradeofferid : offer.tradeofferid
});
}
}
}
deferred.resolve(checkItems_g);
});
return deferred.promise;
}
function getPartnerInventory(offers, offer, itemIds, itemIds_g) {
var p1 = loadPartnerInventory({
partnerSteamId: offer.steamid_other,
appId: 730,
contextId: 2
},itemIds,offers,offer);
var p2 = loadMyInventory({appId: 730, contextId: 2},itemIds_g,offers,offer);
return Q.all(p1, p2).spread(function(checkItems, checkItems_g) {
return {
checkItems: checkItems,
checkItems2: checkItems_g
};
});
}
im doing this to get results, but somehow the second prommiss is undefined and i dont understand why.
getPartnerInventory(offers,offer,itemIds,itemIds_G).then(function(response) {
console.log(response);
//console.log(response);
});
checkitems returns correctly yet checkitems 2 is undefined.
cosole log is :
{ checkItems:
{ itemname: 'Operation Breakout Weapon Case',
market_hash_name: 'Operation Breakout Weapon Case',
steamid: '76561198245431424',
tradeofferid: '859881697' },
checkItems2: undefined }
Pushed: Glock-18 | Wraiths
as can see it its undiefined but seems to add item after its done
You cannot resolve the same promise twice. You should wrap both methods in separate promises and then use Q.all(), which will return a new promise to be resolved only after both promises have been successfully resolved. For example:
function mapOfferItem(item, offer) {
return {
itemname: item.market_name,
market_hash_name: item.market_hash_name,
steamid: args.offer.steamid_other,
tradeofferid : args.offer.tradeofferid
};
}
function loadPartnerInventory(args) {
var deferred = Q.defer();
offers.loadPartnerInventory(args, function(err, items) {
var checkedItems = items.filter(function(item) => {
return args.itemIds.indexOf(item.id) >= 0;
}).map(function(item) {
return mapOfferItem(item, args.offer);
});
deferred.resolve(checkedItems);
});
return deferred.promise;
}
function loadMyInventory(args) {
var deferred = Q.defer();
offers.loadMyInventory(args, function(err, items) {
var checkItems = items.filter(function(item) {
return args.itemIds_g.indexOf(item.id);
}).map(function(item) {
return mapOfferItem(item, args.offer);
});
deferred.resolve(checkItems);
});
return deferred.promise;
}
function getPartnerInventory(offers, offer, itemIds, itemIds_g) {
var p1 = loadPartnerInventory({
partnerSteamId: offer.steamid_other,
appId: 730,
contextId: 2
});
var p2 = loadMyInventory({appId: 730, contextId: 2});
return Q.all([p1, p2]).spread(function(checkItems, checkItems_g) {
return {
checkItems: checkItems,
checkItems2: checkItems_g
};
});
}
You can then use the function like this:
getParentInventory(offers, offer, itemIds, itemIds_g)
.then(function(checkItems) {
console.log(checkItems);
// should print {checkItems: [...], checkItems2: [...]}
});

How to send result after executing all queries

I've got following code
var data=[];
var i = 0,
j = 9;
async.whilst(function () {
return i <= j;
}, function (next) {
connection.query('select * from table', function (err,rows, field) {
data.push(rows.length);
console.log(data);
});
i++;
next();
}, function (err) {
console.log(data);
});
I want to execute the query first and then return result. How should I do it. I've also done it with simple for loop but does not work.
I think you just need to call next() after getting the result of the query:
var data = [];
var i = 0;
var j = 9;
async.whilst(
function () { return i <= j; },
function (next) {
i++;
connection.query('select * from table', function(err, rows, field) {
data.push(rows.length);
console.log(data);
next();
});
},
function (err) {
console.log(data);
}
);
Here is another simple solution with async/await if you use babeljs:
(async function() {
let data = [];
let i = 0;
const j = 9;
while (i <= j) {
let length = await new Promise((resolve, reject) => {
connection.query('select * from table', function(err, rows, field) {
if (err) return reject(err);
resolve(rows.length);
});
});
data.push(length);
}
return data;
})()

Resources