my callback method executes to early. CreateIndexMaxFrame should start after CreateIndexFrame is done. But it starts while "CreateIndexFrame" is still indexing. Also the function console.log("Done") should executed when everthing is done. But it also starts to early.
createIndexFrame(dbObject, collectionName,function()
{
createIndexMaxFrame(dbObject, collectionName,function()
{
io.emit('message', { text: "Fertig" });
db.close();
console.log("DONE");
});
});
function createIndexFrame(dbObject,collectionName, callback)
{
dbObject.collection(collectionName).createIndex({frame:1, temp:-1},function(err, res) {
if (err) throw err;
callback();
});
}
function createIndexMaxFrame(dbObject,collectionName, callback)
{
dbObject.collection(collectionName).createIndex({maxFrame:-1},function(err, res) {
if (err) throw err;
callback();
});
}
https://i.ibb.co/bPzK3Bq/callback.png screenshot
The screenschot is a log by Docker and will show the issue. Mongo_1 shows all MongoLogs. Fill_db_1 is the programm which execute createIndexFrame, createIndexMaxFrame.
As you can see MongoDB will create 2 Indexs parallel.
[conn5] = is createIndexFrame()
[conn2] = is createIndexMaxFrame()
Also the message "DONE" is alredy showing. Although createIndexMaxFrame is not finished.
Related
I tried to define local variable then call lambda function which populates the value to my local variable:
var listOfAliases = null;
lambda.invoke(params, function(err, data) {
if (err) {
//context.fail(err);
console.log(`This is the ERROR execution =${err} =================================`);
prompt(err);
} else {
//context.succeed('Data loaded from DB: '+ data.Payload);
listOfAliases = JSON.stringify(data.Payload);
console.log(`This is the VALIDE execution =${data.Payload} =================================`); //I can see this in the log with proper values
console.log(`This is the VALIDE execution(listOfAliases) =${listOfAliases} =================================`); //I can see this in the log with proper values
}
callback(null, JSON.parse(data.Payload));
});
console.log(`This is the DB execution listOfAliases=${listOfAliases} =================================`); //I can see this in the log with NULL value
The problem here is that lambda.invoke executes asynchronously and your last console.log executes before the invoke callback function completes.
If you need to access the result from outside one the asynchronous call completes, you could use a promise.
var promise = new Promise(function(resolve,reject){
lambda.invoke(params, function(err, data) {
if (err) {
reject(err);
} else {
resolve(JSON.stringify(data.Payload));
}
});
});
promise.then(function(listOfAliases){
console.log('This is the DB execution listOfAliases ' + listOfAliases);
});
I'm totally new to nodejs. I would like to ask your expertise regarding for error handling using connection.beginTransaction(); with this sample code.
connection.beginTransaction(function(){
async.parallel([
function(callback){
connection.query('INSERT INTO SUBJECT.PROJECT (Name, Score) VALUES (?,?)',
['Drake', '85']
, function(error){
//if(error)
// connection.rollback();
callback(error);
});
},
function(callback){
connection.query(someUpdateQuery, someValues,
function(error){
//if(error)
// connection.rollback();
callback(error);
});
}
], function(error){
var msg;
if(error) {
connection.rollback();
msg = 'Error! ' + error;
}
else {
connection.commit();
msg = 'Success';
}
res.json(msg);
});
});
With this sample code, Is this doable?
Every connection.query has connection.rollback() in if(error), can I remove connection.rollback() in each
connection.query and rely in the last function instead to handle the
connection.rollback()? - will it rollback all (lets say) 10 inserting query functions then the 5th 1 got the error.
Sorry, I don't know much,. thanks for reading
You are correct - you can remove the rollback statements of the individual queries and rely on the one in the async.parallel callback. Your code would look something like this:
connection.beginTransaction(function () {
async.parallel([
function (callback) {
connection.query('INSERT INTO SUBJECT.PROJECT (Name, Score) VALUES (?,?)',
['Drake', '85']
, callback);
},
function (callback) {
connection.query(someUpdateQuery, someValues, callback);
}
], function (error) {
var msg;
if (error) {
connection.rollback();
msg = 'Error! ' + error;
}
else {
connection.commit();
msg = 'Success';
}
res.json(msg);
});
});
This works because non of the commands will be committed to the database until you call connection.commit() in the final callback. One thing you might want to look at is whether the commit and rollback methods are asynchronous, i.e. they expect you to pass a callback to them. If so your code as it is will run res.json before the transaction has been committed or rolled back.
this question is related with an answer to my previous question. there #robertklep recommends me to use mapLimit() instead of .map() because .map() can't handle a large series of data, and with that solution all works fine. But now I restructured my code, and now neither of the .<fn>Limit() functions run after the first loop iteration. do I missing something here?
var proccesBook = function(file, cb) {
testFile(file, function (epub) {
if (epub) {
getEpuData(file, function (data) {
insertBookInDB(data)
})
}else{
cb(file)
}
})
}
async.mapLimit(full_files_path, 10, proccesBook, function(err){
if(err){
console.log('Corrupted file', err);
} else {
console.log('Processing complete');
};
})
// ---> only runs for the first 10 series data
Your primary issue is you don't call cb in the success branch of processBook. Your control flow must guarantee to call the callback exactly once for each worker function invocation.
Other asides:
You don't seem to need the results, so eachLimit is fine
Only need mapLimit if you need the results of each worker
You need to follow the standard error-first convention when calling the callback. Don't do cb(file) as that will be interpretted as an error and about the remaining processing.
var proccesBook = function(file, cb) {
testFile(file, function (epub) {
if (epub) {
getEpuData(file, function (data) {
insertBookInDB(data)
cb() // This is what you were missing
})
}else{
cb()
}
})
}
async.eachlimit(full_files_path, 10, proccesBook, function(err){
if(err){
console.log('Corrupted file', err);
} else {
console.log('Processing complete');
};
})
thanks for your help...struggling big time with how to handle this properly. I'm in async now, having given up on my ability to write the callbacks properly. I have snippet where I'm passing a set of random numbers (eachrecord) and passing them through to a mongoose call. Trying to create a data set from the multiple queries I pass.
My issue is that no matter what I've done for 4 hours, the "newarray" variable is always empty.
Thank you for your help -
async.forEach(arLimit, function(eachrecord, callback){
newarray = new Array;
var query = UGC_DB_Model.find({}).skip(eachrecord).limit(-1);
query.execFind(function (err, data) {
if (err)
console.log(err);
else {
newarray.push(data);
}
});
callback(null, newarray);
}, function(err, result) {
if (err) return next(err);
console.log("(it's empty): " + result);
});
There are several issues with your code:
async.forEach isn't meant to 'generate' results, that's what async.map is for;
you need to call the callback only when execFind is done, and not immediately after calling it;
your newarray is probably not necessary;
So try this instead:
async.map(arLimit, function(eachrecord, callback){
var query = UGC_DB_Model.find({}).skip(eachrecord).limit(-1);
query.execFind(function (err, data) {
if (err)
callback(err); // pass error along
else {
callback(null, [ data ]);
// although I think you mean this (because 'data' is probably an array already)
// callback(null, data);
}
});
}, function(err, result) {
if (err) return next(err);
console.log("(it's empty): " + result);
});
I want to use async to make node.js work something in order, first query two rates from mongodb,then use these rates to compute two new rate:
async.series([
function(callback){
db.collection('heros',function(err,collection){
if(err){
console.log(err);
}
if(!err){
console.log("2 collection fetched!");
collection.findOne({'id':win},function(err,result){
if (err) throw err;
rate1=result.rate;
console.log("win-rate:"+rate1);
});
collection.findOne({'id':lose},function(err,result){
if (err) throw err;
rate2=result.rate;
console.log("lose-rate:"+rate2);
});
}
});
callback(null);
}, function(callback){
var Ea= 1/(1+Math.pow(10,(rate2-rate1)/400));
var Eb= 1/(1+Math.pow(10,(rate1-rate2)/400));
var ra= rate1+16*(1-Ea);
var rb= rate2+16*(0-Eb);
console.log("ra:"+ra);
console.log("rb:"+rb);
callback(null);
},
function(callback){
db.collection('heros',function(err,collection){
if(!err){
collection.update({'id':win},{$set: {rate:ra}},function(err,result){
if(err) throw err;
if(!err){
console.log("update successful");
}
});
collection.update({'id':lose},{$set:{rate:rb}},function(err,result){
if(err) throw err;
if(!err){
console.log("update successful");
}
});
}
});
callback(null);
}
]);
but when I run it, it shows error messages:
ReferenceError: ra is not defined
it seems that nodejs jumps to computing or updating without waiting for the query complete.
You're declaring the variables like ra inside of a function block, so they're scoped to that function and unavailable elsewhere. You'd need to put them somewhere more accessible. For example, you could put them in a global variable:
var ra;
async.series([ ... ]);
Further, when you use series, you should call the callback function only when all of the work for that step has completed.
For example, one task should look like this:
db.collection('heros',function(err,collection){
if(err){
console.log(err); // log the error
callback(err); // call the async call back with the error
return; // stop
}
console.log("2 collection fetched!");
collection.findOne({'id':win},function(err,result){
if (err) { callback(err); return; } // again, handle error
rate1 = result.rate; // grab results
console.log("win-rate:"+rate1); // log
callback(null, rate1); // now indicate complete by calling
});
});
As you've got multiple async function calls within a single task, you may want to split them to multiple tasks or consider using the parallel function as well. You could even use parallel within one of the other tasks in the series call to handle the case where you have two findOne calls that need to be made.