I was reading this article here about calling an asynchronous function within Although it worked fine, I noticed something which wasn't quite what I expected...forEach
and I did a little experiment for my own.
EDIT: Commented out the reference to the article above for it just misleads readers and brings confusions. My primary concern is about Javascript loops in general, and has nothing to do with async functions as the referred article discusses.
In the code, I have a console output like this:
timer.show('[0] res[' + lastindex + ']: '
+ (typeof res[lastindex] != 'undefined' ? res[lastindex] : 'NA'));
which is located RIGHT AFTER THE LOOP.
I thought it would be executed immediately when it is located just bellow the loop, especially when the array is relatively huge.
But, what I got was this:
[created] array with 550000
[1,2,3]
[4,5,6]
[7,8,9]
....
[0] res[549999]: NA (elapsed: 4 msec)
[2] res[549998]: 4949988 (elapsed: 223 msec)
[3] res[549999]: 4949997 (elapsed: 224 msec)
[1] res[549999]: 4949997 (elapsed: 224 msec) <--- HERE
[4] res[549999]: 4949997 (elapsed: 236 msec)
done!
So, here's my question....
Why is it that my [1]
output waits for the loop to end?
I try the code on other browsers (other than Chrome which I usually work with), I also tried using map
and for
to see if I get different results, but they were all the same...
Please, I need explanations on this.... is this intended behavior?
Note: I'm talking about browser execution, not Node.js here
(fn => {
// Just creating a huge array for the test.
let arr = [];
let max = 550000; // This seems appropriate
// for stackoverflow snippet execution.
// (or around 10000000 for my browser)
let n = 1;
for (let i=0; i<max; i++) {
arr.push([n++, n++, n++]);
if ((i + 1) >= max) {
fn(arr);
}
}
})(arr => {
// Now, the test begins!
let timer = simple_timer_factory();
let timer_id = timer.beg();
let size = arr.length;
let lastindex = (size - 1);
console.log('[created] array with ' + size);
console.log(' ' + JSON.stringify(arr[0]));
console.log(' ' + JSON.stringify(arr[1]));
console.log(' ' + JSON.stringify(arr[2]));
console.log(' ....');
let res = [];
// Peeping the last element even before the loop begins.
timer.show('[0] res[' + lastindex + ']: '
+ (typeof res[lastindex] != 'undefined' ? res[lastindex] : 'NA'));
arr.forEach((item, i, arr) => {
res.push(item.reduce((a, b) => {
return a + b;
}));
// The element right before the last.
if (i == (lastindex - 1)) {
timer.show('[2] res[' + i + ']: ' + res[i]);
}
// The last element.
if (i == lastindex) {
timer.show('[3] res[' + i + ']: ' + res[i]);
}
});
// Peeping inside the last element before the loop ends!?
timer.show('[1] res[' + lastindex + ']: '
+ (typeof res[lastindex] != 'undefined' ? res[lastindex] : 'NA'));
// To double make sure, we use "setInterval" as well to watch the array.
let id = window.setInterval(() => {
let lastindex2 = (res.length - 1);
if (lastindex2 >= lastindex) {
window.clearInterval(id);
id = void 0;
timer.show('[4] res[' + lastindex2 + ']: ' + res[lastindex2]);
timer.end(timer_id);
console.log('done!');
}
}, 10);
});
/**
* This has nothing to do with the main question here.
* It will keep track of the time elapsed.
* @returns {Object}
*/
function simple_timer_factory() {
var init, prev, curr;
return Object.create({
beg(fn) {
init = prev = curr = Date.now();
( window.requestAnimationFrame ||
window.webkitRequestAnimationFrame ||
function(tick){
return window.setTimeout(
tick, Math.ceil(1000 / 30)
);
}
)(fn || function(){});
},
snapshot() {
curr = Date.now();
return {
prev,
curr,
elapse: curr - init,
delta: curr - prev
};
},
show(msg) {
console.log(
(msg ? (msg + ' '): '')
+ '(elapsed: '
+ this.snapshot().elapse + ' msec)');
},
end(timer_id) {
prev = curr = void 0;
( window.cancelAnimationFrame ||
window.webkitCancelAnimationFrame ||
function(id){
if (id) {
window.clearTimeout(id);
}
}
)(timer_id);
}
});
}
SOLVED: It was based on my prejudice about Javascript language. I thought Javascript does not wait for forEach
or for
to end, but it was no different than other languages like PHP or Perl. It actually waits for the loop to end.
with a normal for loop, it will function like a normal for loop in any other language. – khazhyk
EDIT: EDIT: I found the exact answer here.
Loops are synchronous in Node.js and JavaScript and synchronous code always runs to completion. So if you're not making calls to asynchronous functions you can rest assured that your code will not be interrupted until it finishes.