I am given a function like this:
//! Work on record.
/*!
\param[in] Record (object) Record.
\param[in] AsyncCallback (function) Asynchronous callback which is called when the operation is complete. It takes no parameters.
*/
function WorkOnRecord(Record, AsyncCallback)
{
/* Work on Record asynchronously (e.g. by calling $.ajax())
and call AsyncCallback on complete. */
}
Now, I have an array of objects (RecordArray
) that I need to feed to the above function, one by one, meaning that I have to wait until it callbacks before calling it the next time.
So I came up with:
$(function() {
var RecordArray = SomeOtherFunc(); // RecordArray is an array of objects.
// Work on records, one by one.
var RecordIndex = 0;
var WorkFunc = function() {
// If there are still records to work on...
if(RecordIndex < RecordArray.length)
{
// Work on record.
WorkOnRecord(RecordArray[RecordIndex], function() {
// Move forward to next record.
WorkFunc();
});
RecordIndex++;
}
// If there are no more records to work on...
else
{
/* We are all done. */
}
};
WorkFunc(); // Start working.
});
As you can see, WorkFunc
is actually called from within the anonymous function on which the variable WorkFunc
itself is defined. Is this legal in ECMAScript/Javascript? (legal meaning that it works on all standard-compliant browsers)
I mean, to me, it is pretty much like var c = c + 1;
in Javascript or int c = c + 1;
in C/C++/ObjC/Java, which is referencing a variable while defining it, so either it should be illegal or it's behaviour should be undefined.
However, it seems to work fine on a few browsers.
After some more research and thinking, I came up with other solutions.
- Solution 1: Naming the anonymous function (
MyFunc
), so that I can use its name inside (reference here).
Code:
var WorkFunc = function MyFunc() { // Name it MyFunc.
if(RecordIndex < RecordArray.length)
{
WorkOnRecord(RecordArray[RecordIndex], function() {
MyFunc(); // Use MyFunc here
});
RecordIndex++;
}
};
WorkFunc();
- Solution 2: Use a function declaration instead of a function expression, so that it is more like a recursive function (although not exactly) (reference here).
Code:
function WorkFunc() { // Declare function.
if(RecordIndex < RecordArray.length)
{
WorkOnRecord(RecordArray[RecordIndex], function() {
WorkFunc();
});
RecordIndex++;
}
};
WorkFunc();
- Solution 3: Passing the variable as a parameter (
NextStepFunc
), so that I don't need to referenceWorkFunc
inside (this looks so funny).
Code:
var WorkFunc = function(NextStepFunc) { // Accept function as parameter.
if(RecordIndex < RecordArray.length)
{
WorkOnRecord(RecordArray[RecordIndex], function() {
NextStepFunc(NextStepFunc); // Call function as defined by parameter.
});
RecordIndex++;
}
};
WorkFunc(WorkFunc); // Pass function as variable to parameter.
But my question still stands: was my original solution legal?