Redis in Nodejs for loop not working properly - node.js

I have a for loop like below which isn't getting executed as expected.
var redis = require('redis');
var client = redis.createClient();
var arr = [{title:"title1"},{title:"title2"},{title:"title3"},{title:"title4"}];
for(var i =0; i<arr.length; i++){
//console.log(arr[i]);
var obj1 = arr[i];
client.get(obj1.title, function(err, response){
if(err){
console.log(err);
}
if(response){
if(i%3==0){
client.del(obj1.title);
}else{
client.incr(obj1.title);
}
}else{
client.set(obj1.title, 1);
}
});
}
The output on running the below code afterwards was
for(var i=0; i<arr.length; i++){
client.get(arr[i].title, redis.print);
}
The output:
Reply: null
Reply: null
Reply: null
Reply: null
Reply: null
Reply: null
Reply: 2
which was not what i expected, since all values except the one divisible by 3 should be atleast 1;

Please create a new function. In the new function, you can delete, increment or creating the new key.
The below code works fine for me. Please check.
var redis = require('redis');
var client = redis.createClient();
var arr = [ {
title : "title1"
}, {
title : "title2"
}, {
title : "title3"
}, {
title : "title4"
} ];
function delOrIncr(obj1, i) {
client.get(obj1.title, function(err, response) {
if (err) {
console.log(err);
}
if (response) {
if (i % 3 === 0) {
console.log('Deleting >' + obj1.title);
client.del(obj1.title);
} else {
console.log('Increment >' + obj1.title);
client.incr(obj1.title);
}
} else {
console.log('Creating new >' + obj1.title);
client.set(obj1.title, 1);
}
});
}
for (var i = 0; i < arr.length; i++) {
delOrIncr(arr[i], i);
}
Note:-
Please run the get as a separate program to check the result of the above program.

var redis = require('redis');
var client = redis.createClient();
var arr = [{title:"title1"},{title:"title2"},{title:"title3"},{title:"title4"}];
for(var i =0; i<arr.length; i++){
//console.log(arr[i]); // this is cool
var obj1 = arr[i];
client.get(obj1.title, function(err, response){
if(err){
console.log(err);
}
if(response){
if(i%3==0){
// mistake 1:
// due to async op,loop will already be over and i will be 3 here
// mistake 2:
// obj1 will be arr[3] here, not what you were expecting :D
client.del(obj1.title);
}else{
client.incr(obj1.title);
}`enter code here`
}else{
// so only the last obj gets stored.
client.set(obj1.title, 1);
}
});
}

Related

Array is empty, no data after for loop added

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

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

node.js how to get data from redis database inside in middleware

I'm doing middleware module that will extract data from redis and put to req.my_session.[here]
This is function that call inside app.use();
function parse_cookies(req){
if(req.headers.cookie != null){
var result = req.headers.cookie.match(new RegExp('m:[^=]*=[^; ]*', 'ig'));
if(result != null){
for(var i = 0; i < result.length; i++){
var result1 = result[i].split('=');
req.my_session[result1[0].substr(2)] = result1[1];
// get from redis value
client.get('sess:'+result1[1], function(err, reply) {
// reply is null when the key is missing
console.log(reply);
let li = i;
req.my_session[result1[0].substr(2)] = reply;
console.log('li = ' + li);
console.log('result1.lenght= ' + result.length);
if(i == result.length){
console.log('call the next');
}
});
}
}
}
} // parse_cookies
in console i outputs always 3, how can I get all data from database using redis.get and on last data call next() function for get out from my function?
problem it's get data from database in my middleware, I can't because redis has callback function
client.get("missingkey", function(err, reply) {
// reply is null when the key is missing
console.log(reply);
});
I think the issue is becuase of async in loop you can try the following
function parse_cookies(req){
if(req.headers.cookie != null){
var result = req.headers.cookie.match(new RegExp('m:[^=]*=[^; ]*', 'ig'));
if(result != null){
var promises = [];
for(var i = 0; i < result.length; i++){
var result1 = result[i].split('=');
promises.push(getFromRd(req, result1));
}
return Promise.all(promises)
.then(() => {
return next()
})
.catch((e) => {
return next({error: e})
})
}
}
} // parse_cookies
function getFromRd(req, result1) {
req.my_session[result1[0].substr(2)] = result1[1];
// get from redis value
return client.get('sess:'+result1[1], function(err, reply) {
if (err) {
throw Error(' failed to find ' + 'sess:' + result1[1])
}
// reply is null when the key is missing
console.log(reply);
let li = i;
req.my_session[result1[0].substr(2)] = reply;
console.log('li = ' + li);
console.log('result1.lenght= ' + result.length);
return {success:true}
});
}

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: [...]}
});

Nodejs MongoDB updating documents with asynchronous function

I'm new to NodeJS and MongoDB. Is there a way to update a document using asynchronous functions in nodejs? I have a collection of websites with documents: _id, name and registrant. I want to insert a value in registrar using an asynchronous function. The function is a system call, and I just parse the output that I want. Running the code, the async function logs the information I want but does not store in the database. Any suggestions on how I can solve this? Thanks.
/*
* { _id: 53448014b15c693931000002,
* name: 'google.com',
* registrant: 'defaultval' } */
var MongoClient = require('mongodb').MongoClient;
var ObjectID = require('mongodb').ObjectID;
var id = '53448014b15c693931000002';
var domain = 'google.com';
MongoClient.connect('mongodb://127.0.0.1:27017/mydb', function(err, db) {
if (err) throw err;
var collection = db.collection('websites');
collection.findAndModify({_id:new ObjectID(id)},
{},
{$set: {registrant: test(domain, function (output) {
var t = output.split("\n");
for (var i = 0; i < t.length; ++i) {
if (t[i].indexOf("Registrant Organization:") != -1) {
console.log(t[i].substring(t[i].indexOf(":") + 2, t[i].length));//prints correct value, need this to store in registrant doc
return t[i].substring(t[i].indexOf(":") + 2, t[i].length);
}
}
})}},
{},
function(err, object) {
if (err) console.log(err.message);
else {
console.log(object);
}
db.close();
});
});
var test = function(domain, cb) {
var sys = require('sys');
var exec = require('child_process').exec;
var child = exec('whois ' + domain, function(error, stdout, stderr) {
cb(stdout);
});
}
Start one process on core:
var cluster = require('cluster')
, numCPUs = require('os').cpus().length
, windows = require('os').platform() == 'win32';
if(cluster.isMaster) {
// Fork workers.
for (var i = 0; i < numCPUs; i++) {
cluster.fork();
}
cluster.on('exit', function(worker, code, signal) {
console.log('worker ' + worker.pid + ' died');
});
return;
}
Create function to be async:
function mongodbDriverQuery(callback) {
collection.findOne({ id: getRandomNumber()}, function(err, world) {
callback(err, world);
});
}
http.createServer(function (req, res) {
// JSON response object
var hello = {message: "Hello, World!"};
var helloStr = "Hello, World!";
var path = url.parse(req.url).pathname;
// mysql on windows is not supported
if (windows && (path.substr(0, 3) == '/my' || path == '/update')) {
path = '/doesntexist';
}
switch (path) {
case '/mongodbdriver':
// Database Test
var values = url.parse(req.url, true);
var queries = values.query.queries || 1;
var queryFunctions = new Array(queries);
for (var i = 0; i < queries; i += 1) {
queryFunctions[i] = mongodbDriverQuery;
}
res.writeHead(200, {'Content-Type': 'application/json; charset=UTF-8'});
// and run it
async.parallel(queryFunctions, function(err, results) {
if (queries == 1) {
results = results[0];
}
res.end(JSON.stringify(results));
});
break;

Resources