For loop value skipped in loop - node.js

I have this for loop in my node.js application:
for (var runNumber=1; runNumber<=numberOfRuns; runNumber++) {
runNumberQueue.place(function(){
versionRunningService.runMultiVersionJobs(
queue, jobId, sVersion, jobType, runNumber, currentConfig, allJobsConfig, appDir, function(){
runNumberQueue.next();
currentIterationCount++;
if (currentIterationCount === numberOfIterations) {
callback();
}
});
});
}
Is there somethingwrong with the structure of it? It seems to increment runNumber then execute the runNumberQueue.place function with runNumber 1, skip execution of runNumberQueue.place for runNumber 2 and execute again correctly for runNumber 3.
I wondered if it could be some asynch issue either but think that runNumberQueue.place would execute with runNumber 2 at some stage?

The way JavaScript works inside loops is that the variable defined inside the loop score (e.g., runNumber here) are bound to the same scope. So when you run an anonymous function inside the loop, it uses those variables bound to the loop scope, and not the function scope.
This is a common situation in JS loops. To avoid this, you can either define a secondary variable to capture the value of loop index variable or define an external function instead of the anonymous function.
A secondary variable:
for (var runNumber=1; runNumber<=numberOfRuns; runNumber++) {
var runNumberCopy = runNumber;
runNumberQueue.place(function(){
versionRunningService.runMultiVersionJobs(
queue, jobId, sVersion, jobType, runNumberCopy, currentConfig, allJobsConfig, appDir, function(){
runNumberQueue.next();
currentIterationCount++;
if (currentIterationCount === numberOfIterations) {
callback();
}
});
});
}
An external function:
for (var runNumber=1; runNumber<=numberOfRuns; runNumber++) {
placeRunNumberQueue(runNumber);
}
// this function can be defined elsewhere and passed all the required arguments
function placeRunNumberQueue(runNumber) {
runNumberQueue.place(function(){
versionRunningService.runMultiVersionJobs(
queue, jobId, sVersion, jobType, runNumber, currentConfig, allJobsConfig, appDir, function(){
runNumberQueue.next();
currentIterationCount++;
if (currentIterationCount === numberOfIterations) {
callback();
}
});
});
}
There is another post going over this issue in more details.

Related

Why is the middleware named in the below example [duplicate]

I have a major problem with profiling in javascript with anonymous functions, I have always many anonymous functions - most of them are callbacks - and It makes analyzing results of profiler very hard for me.
Finally I decided to use named functions for callbacks, like this:
var f = function(callback) {
// Do something ...
callback();
}
f(function named_function() {
console.log('Sample callback function!');
});
I want to know that will I have any problems after making this change in my codes?
And will this type of function definition and passing reserve the name (named_function) anywhere?
The name will only be available inside the scope of the named function expression.
But there is a problem in IE 8 and lower. It will leak out to the outer scope, and will actually create a different function object, so you should nullify it if that's a problem.
f(function named_function() {
console.log('Sample callback function!');
});
var named_function = null;
See this article for more information: Named function expressions demystified
Or you could create it like this to solve the IE issue.
f(function() {
return function named_function() {
console.log('Sample callback function!');
};
}());
But that's a little ugly.
If you pass anonymous functions like that, the name will exist inside the function itself.
It will not exist in any other scope.
var f = function(callback) {
// Do something ...
callback();
}
f(function named_function() {
console.log(named_function); // Logs the function
console.log('Sample callback function!');
});
console.log(named_function);​ // Error: named_function is undefined
You don't have to complicate things.
Just name the function when you declare it
var foo = function foo(){};
Defining a named callback in a scope will cause it to be visible only in that scope. I would therefore conclude that there shouldn't be any naming conflicts. For example, the following code runs as expected:
(function named_callback() { console.log("Callback 1"); })();
(function named_callback() { console.log("Callback 2"); })();​
Actually, you're still creating an anonymous function expression and assigning it to a local scoped variable f. Go for
function f( callback ) {
callback();
}
f( named_function );
function named_function() {
console.log('Sample callback function!');
}
That way, you're even avoiding the named function expression memory leak in <= IE8, plus since you're no longer creating a function expression but a *function declaration, you can even access f within the body.

Avoid callback multi-invocation when forEach is used

I have a function that processes an array of data (first parameter) and, once the procesing is finished, it invokes only one time a callback function (second parameter). I'm using forEach to process data item by item, consisting the processing of each item in some checkings and storing the param in database. The function storeInDB() does the storing work and uses a callback (second parameter) when the item has been stored.
A first approach to the code is the following:
function doWork(data, callback) {
data.forEach(function (item) {
// Do some check on item
...
storeInDB(item, function(err) {
// check error etc.
...
callback();
});
});
}
However, it's wrong, as the the callback function will be invoked several times (as many as element in the data array).
I'd like to know how to refactor my code in order to achieve the desired behaviour, i.e. only one invocation to callback once the storing work is finished. I guess that async could help in this task, but I haven't find the right pattern yet to combine async + forEach.
Any help is appreciated!
You can use a library such as async to do this, although I would recommend using promises if possible. For your immediate problem you can use a counter to determine how many storage calls have completed and call the callback when the total number are completed.
let counter = 0;
data.forEach(function (item) {
// Do some check on item
...
storeInDB(item, function(err) {
// check error etc.
counter++
if (counter == data.length) {
callback();
}
});
});
you can also utilize the three parameters passed to the function to execute on each array method
function doWork(data, callback) {
data.forEach(function (value,idx,arr) {
// Do some check on item
...
storeInDB(arr[idx], function(err) {
// check error etc.
...
if ( (idx + 1) === arr.length ) {
callback();
}
});
});
}
If storeInDB function returns a promise, you can push all async functions to an array and use Promise.all. After all tasks run successfully, It will invokes callback function.
Hope this helps you.
function doWork(data, callback) {
let arr = [];
data.map(function(itm) {
// Do some check on item
...
arr.push(storeInDB(item));
});
Promise.all(arr)
.then(function(res) {
callback();
});
}

NodeJS callback is calling too early

I am running the following two functions one after the other. When runScript() finishes the callback function should be triggered. However these functions are running asynchronously, and data from the first function (which is required for the second function) returns as undefined.
I am new to callback functions, and am possibly approaching this incorrectly. I've omitted insertAssets() and insertPairs() for clarity, but their code is asynchronous and involves DB calls.
function runScript(cb) {
for(var name in exchange_objects) {
insertAssets(exchange_objects[name].assets, name); // runs some async code
}
cb();
}
runScript(function() {
for(var name in exchange_objects) {
insertPairs(exchange_objects[name].pairs, name); // runs some async code
};
});

Confusion related to node.js code

I found this code where it says that I can run some db queries asynchronously
var queries = [];
for (var i=0;i <1; i++) {
queries.push((function(j){
return function(callback) {
collection.find(
{value:"1"},
function(err_positive, result_positive) {
result_positive.count(function(err, count){
console.log("Total matches: " + count);
positives[j] = count;
callback();
});
}
);
}
})(i));
}
async.parallel(queries, function(){
// do the work with the results
}
I didn't get the part what is callback function how is it defined ? second in the queries.push, it is passing the function(j) what is j in this and what is this (i) for
queries.push((function(j){})(i));
I am totally confused how this code is working?
The loop is preparing an array of nearly-identical functions as tasks for async.parallel().
After the loop, given it only iterates once currently, queries would be similar to:
var queries = [
function (callback) {
collection.find(
// etc.
);
}
];
And, for each additional iteration, a new function (callback) { ... } would be added.
what is callback function how is it defined ?
callback is just a named argument for each of the functions. Its value will be defined by async.parallel() as another function which, when called, allows async to know when each of the tasks has completed.
second in the queries.push, it is passing the function(j) what is j in this and what is this (i) for
queries.push((function(j){})(i));
The (function(j){})(i) is an Immediately-Invoked Function Expression (IIFE) with j as a named argument, it's called immediately with i a passed argument, and returns a new function (callback) {} to be pushed onto queries:
queries.push(
(function (j) {
return function (callback) {
// etc.
};
})(i)
);
The purpose of the IIFE is to create a closure -- a lexical scope with local variables that is "stuck" to any functions also defined within the scope. This allows each function (callback) {} to have its own j with a single value of i (since i will continue to change value as the for loop continues).
Callback is one of the coolest features. Callback is just another normal function. You can actually pass a function itself as a parameter in another function.
Say function foo() does something. You may want to execute something else right after foo() is done executing. So, in order to achieve this, you define a function bar() and pass this function as a parameter to function foo()!
function foo(callback){
// do something
callback();
}
function bar(){
// do something else
}
foo(bar());
//here we can see that a function itself is being passed as a param to function foo.
For more understanding here's the right link.
And
queries.push((function(j){})(i));
in javascript, this is another way of calling a function.
function(){
// do something.
}();
You don't actually need to define a function name and it can be called directly without a name. You can even pass params to it.
function(a){
alert(a)'
}(10);

Propogation of *this* in nested function calls in Backbone.js

I started using backbone.js recently for a game. I used model to create Timer as follows:
var Timer = Backbone.Model.extend({
defaults: {
'hh':00, 'mm':05, 'ss':00
},
initialize: function() {
},
countDownOnce: function() {
// Count down the time by 1 sec
},
run1: function() {
this.countDownOnce();
}
run2: function() {
setInterval(this.countDownOnce, 1000);
}
});
The countDownOnce function, if called directly as in run1, works fine.
But if the function is passed as an argument to some built-in function, say setInterval as in the run2 function, the value of this is lost.
How to propagate this pointer to the built-in functions?
The Backbone docs have a useful section on binding "this".
Basically, Underscore provides a couple of very useful functions, _.bind and _.bindAll, which help you more easily manage 'this's context.
...
initialize: function() {
_.bindAll(this, 'countDownOnce' //, and whatever other functions you want bound)
}),
...
This will make sure that no matter what context it's called from, the 'this' inside countDownOnce refers to your Timer instance.
One way to do this is using call and apply. For example:
run2: function() {
setInterval(this.countDownOnce.call, 1000, this);
}
Also note that passing a closure/function reference with arguments to setTimeout() and setInterval() requires some manual hacks to work correctly in IE.
this is how javascript was designed (pun intended :)
Basically 'this' binds to the current context so if in a function/method call like this:
var Data = function(name) {
this.name = name;
}
var myData = new Data("viky");
would refer to the name element "inside" Data (i.e., myData in this case)
Now if you had the following:
var Data = function(name) {
function morphName(anotherName) {
//and if you call this like this ;)
alert(this.name); //undefined
}
}
the inner function morphName is bound to the 'current' context i.e., the outer function. In javascript everything is an object, including functions. So the outer (anonymous) function doesn't have a member called name! (makes sense?)
In order to do that most people use the following (by convention):
var Data = function(name) {
var that = this; //capture current context. Some prefer self = this;
function morphName(anotherName) {
//then you access name like that ;)
alert(that.name);
}
}
I suggest you read about javascript closures and scopes to understand this and that :D

Resources