NodeJS continues executing before object finished initializing - node.js

I'm creating an object in node like this:
obj.push(new MyObject());
here is my object code
function MyObject() {
this.arr= [];
for (x= 0; x< 2; x++) {
this.arr.push([]);
for (y= 0; y< 400; y++) {
this.arr[x].push([]);
for (z= 0; z< 1008; z++) {
this.arr[x][y].push(0);
}
}
}
}
after I call obj.push, program execution continues and the operations at index 1006, 1007... don't work because I suspect the array isn't finished initializing. How can I make sure that the array is initialized before program execution continues?
edit:
for (i = 0; i < 1; i++) {
(function(i) {
asyncTasks.push(function(callback) {
obj.push(new MyObject());
some_class.bigOperation(obj[i], function() {
callback();
});
});
})(i);
}
async.parallel(asyncTasks, function() {
console.log("finished initializing");
});

Not quite sure what you mean by array isn't initialized. You're creating your objects in parallel, which depending on your actual implementation might be the problem. Take a look at this version and see if it helps.
var async = require('async');
var asyncTasks = [];
var obj = [];
function bigOperation(myObj, done) {
setTimeout(function() {
console.log('done with long operation');
done();
}, 1000);
}
function MyObject() {
this.arr = [];
for (x= 0; x< 2; x++) {
var xlayer = [];
this.arr.push(xlayer);
for (y= 0; y< 400; y++) {
var ylayer = [];
xlayer.push(ylayer);
for (z= 0; z< 1008; z++) {
ylayer.push(0);
}
}
}
console.log('obj created');
}
for (i = 0; i < 10; i++) {
var myObj = new MyObject();
obj.push(myObj);
(function(myObj) {
asyncTasks.push(function(callback) {
bigOperation(myObj, callback);
});
})(myObj);
}
console.log('starting async tasks');
async.parallel(asyncTasks, function() {
console.log("finished initializing");
});

use callback, node is async, code is executing line by line but will not wait
initialize = function(callback){
var a = [];
//do your initialization here
callback(a);
}
initialize(function(data){
// array initialized you can now populate it.
});
However, you loop is a bit weird to me. Are you sure you it is correct ?

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

Nodejs async await for loop

How can I wait until the function a is complete, but is not working as I expected.
Here is my code:
var start = Date.now();
function a() {
setTimeout(function(){ console.log(Date.now() - start); }, 500);
for(var i=0; i<100; i++) {
console.log(i);
//
}
}
const main = async () => {
await a();
console.log("Done");
};
main().catch(console.error);
You have to return promise when you call await. The await operator is used to wait for a Promise. It can only be used inside an async function. Check here for more details:
async function
var start = Date.now();
function a() {
return new Promise(function(resolve, reject) {
setTimeout(function(){ console.log(Date.now() - start); resolve()}, 500);
for(var i=0; i<100; i++) {
console.log(i);
//
}
})
}
const main = async () => {
await a();
console.log("Done");
};
main().catch(console.error);
var start = Date.now();
function a() {
return new Promise((resolve, reject)=> {
setTimeout(function(){ console.log(Date.now() - start); resolve() }, 500);
for(var i=0; i<100; i++) {
console.log(i);
//
}
});
}
const main = async () => {
await a();
console.log("Done");
};
main().catch(console.error);
you can use q module for make promise also:
var q = require('q')
var start = Date.now();
function a() {
let defer = q.defer()
setTimeout(function(){ console.log(Date.now() - start); defer.resolve();}, 500)
for(var i=0; i<100; i++) {
console.log(i);
}
return defer.promise;
}
const main = async () => {
await a();
console.log("Done");
};
main().catch(console.error);

node promise loop returning promise not working

I'm new to node, playing with promise loops
on completion of my loop (10 iterations) I want to know that the function has completed, how do I do this?
here is my code
var promise1 = new Promise((resolve, reject) => {
for (let i = 0, p = Promise.resolve() ; i < 10; i++) {
p = p.then(_ =>
new Promise(resolve => {
setTimeout(function () {
console.log(i);
resolve();
}, 50);
}
));
}
});
//start
promise1.then(function (result) {
// Resolve
console.log("done");
}, function (result) {
// Reject
console.error(result);
});
promise1 never completes because you forgot to call resolve() or reject() for it.
Please check the code snippet below. I added comments before the lines I added or changed.
// Use different names for the `resolve` callbacks to be clear which is which
var promise1 = new Promise((res) => {
// Move the declaration of `p` outside the loop to let it be visible after the loop
let p = Promise.resolve();
for (let i = 0; i < 10; i++) {
p = p.then(_ =>
new Promise(resolve => {
setTimeout(function () {
console.log(i);
resolve();
}, 50);
}
));
}
// Chain the completion of the outer promise when `p` resolves
p.then(() => res());
});
//start
promise1.then(function (result) {
// Resolve
console.log("done");
}, function (result) {
// Reject
console.error(result);
});
If you want to resolve multiple promises at a time you can use Promise.all.
What you can do is put every promise into array and resolve by using Promise.all function like below.
var promises = [];
for (let i = 0, i < 10; i++) {
promises.push(new Promise.resolve(i));
}
var results = Promise.all(promises);
console.log(results);
function abc() {
return new Promise(function (resolve, reject) {
var events = [];
for(var i=0;i<5;i++) {
var event_arr = {};
var event_city = {};
event_arr.event_city = {"city":"m-"+i};
events.push(event_arr);
}
if(events) {
resolve(events)
}else {
reject("NOp");
}
}).then((events)=>{
var p = Promise.resolve()
var events2 = [];
var i=0;
events.forEach(function(element) {
p = p.then(() => {
return new Promise(function (resolve, reject) {
var address_info = {};
var event_arr = {};
var event_city = element.event_city;
event_arr.event_cityy = event_city;
setTimeout(function () {
var address_info = {"address":"B-"+i};
console.log(i);
i++;
event_arr.address_info = address_info;
events2.push(event_arr);
// console.log(events2)
//resolve(events2);
if(events2) {
resolve(events2);
}else {
reject("NOp2");
}
}, 5000)
}).then((events2)=>{
return events2;
});
})
});
return p.then((events2)=>{
return events2;
});
});
}
var v = abc();
v.then(function(events2) {
console.log(events2)
console.log("-------X------------")
})

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

Loop synchronous multiple async.whilst

I want to use many included loops in node.js in synchronous mode.
Example :
for (var i = 0; i < length1; i++) {
for (var j = 0; j < length2; j++) {
for (var k = 0; k < length3; k++) {
//completed 3
}
//completed 2
}
//do completed 1
}
How to do this with async? I tried this :
exports.myFunction = function (callback) {
var finalListA = new Array();
var pos = 0;
Model_A.find().populate('listOfItems')
.lean().exec(function (err, As) {
if (err) {
console.log(err);
return callback(err, null);
} else {
//For each A
var i = 0;
async.whilst(
function () {
return i < As.length;
},
function (callback1) {
var isActive = false;
//For each B into the A
var j = 0;
async.whilst(
function () {
return j < As[i].Bs.length;
},
function (callback2) {
Model_B.findById(AS[i].Bs[j]._id, function (err, B) {
if (err) {} else {
var k = 0;
// For each C in the B
async.whilst(
function () {
return k < B.Cs.length;
},
function (callback3) {
if (B.Cs[k].dateEnd >= Date.now()) {
isActive = true;
}
k++;
callback3();
},
function (err) {
console.log("3 COMPLETED");
}
);
}
});
j++;
callback2();
},
function (err) {
console.log("2 COMPLETED");
if (err) {} else {
if (isActive == true) {
finalListA[pos] = As[i];
pos = pos + 1;
}
}
}
);
i++;
callback1();
},
function (err) {
console.log("1 COMPLETED");
if (err) {} else {
return callback(null, finalListA);
}
}
);
}
});
}
The trace shows me :
COMPLETED 2
COMPLETED 2
COMPLETED 1
COMPLETED 3
COMPLETED 3
The order expected is :
COMPLETED 3
COMPLETED 3
COMPLETED 2
COMPLETED 2
COMPLETED 1
You must call the callbacks of the higher loops from the end callback of your whilst loop (like you did with the outermost callback), instead of calling them synchronously from the whilst body in which you just started the next level iteration.
Btw, I don't know what you actually want to do, but whilst does not seem the best choice for iterating arrays. Use the parallel each or the serial eachSeries (or their map or reduce equivalents).
I've recently created simpler abstraction called wait.for to call async functions in sync mode (based on Fibers). It's at an early stage but works. It is at:
https://github.com/luciotato/waitfor
Using wait.for, you can call any standard nodejs async function, as if it were a sync function.
I do not understand exactly what are you trying to do in your code. Maybe you can explain your code a little more, or give some data example.
I dont' know what Model_A or Model_B are... I'm guessing most of your code, but...
using wait.for your code migth be:
var wait=require('wait.for');
exports.myFunction = function(callback) {
//launchs a Fiber
wait.launchFiber(inAFiber,callback);
}
function inAFiber(callback) {
var finalListA = new Array();
var pos = 0;
var x= Model_A.find().populate('listOfItems').lean();
As = wait.forMethod(x,"exec");
//For each A
for(var i=0;i<As.length;i++){
var isActive = false;
//For each B into the A
for(var j=0; j < As[i].Bs.length;j++){
var B=wait.forMethod(Model_B,"findById",AS[i].Bs[j]._id);
// For each C in the B
for(var k=0; k < B.Cs.length;k++){
if(B.Cs[k].dateEnd >= Date.now()) {
isActive = true;
}
}
console.log("3 COMPLETED");
}
console.log("2 COMPLETED");
if(isActive == true) {
finalListA[pos] = As[i];
pos = pos + 1;
}
};
console.log("1 COMPLETED");
return callback(null,finalListA);
}
Also, for what I see, you should break the loops as soon as you find one item (isActive), and you don't need the var pos. Doing that your code will be:
var wait=require('wait.for');
exports.myFunction = function(callback) {
//launchs a Fiber
wait.launchFiber(inAFiber,callback);
}
function inAFiber(callback) {
var finalListA = [];
var x= Model_A.find().populate('listOfItems').lean();
As = wait.forMethod(x,"exec");
var isActive;
//For each A
for(var i=0;i<As.length;i++){
isActive = false;
//For each B into the A
for(var j=0; j < As[i].Bs.length;j++){
var B=wait.forMethod(Model_B,"findById",AS[i].Bs[j]._id);
// For each C in the B
for(var k=0; k < B.Cs.length;k++){
if(B.Cs[k].dateEnd >= Date.now()) {
isActive = true;
break;//for each C
}
} //loop for each C
console.log("3 COMPLETED");
if (isActive) break;//for each B
} //loop for each B
if (isActive) finalListA.push(As[i]);
console.log("2 COMPLETED");
} //loop for each A
console.log("1 COMPLETED");
return callback(null,finalListA);
}

Resources