Have you ever tried to define a callback in a loop like this:
var values = {};
for (var i = 0; i < keys.length; i++) {
getKeyValue(keys[i],function(v){
values[keys[i]] = v;
});
}
While the code above would seem correct at first, it actually has a major problem. If we run the code with keys set to ["key1","key2","key3"]
value would be {"key3":"value3"}
instead of {"key1":"value1","key2":"value2","key3":"value3"}
like expected. To understand why this happens, we must realize that the value of i
changes before the callback is called.
By the time the callback is called, i
is now 2
and so it will only set the last value. Even worse, the value of that is unpredictable as it becomes a race condition between the different getKeyValue()
calls.
A good way to fix this is to use an IIFE, or a function that is called immediately after it is defined. The code below using an IIFE will work as intended:
var values = {};
for (var i = 0; i < keys.length; i++) (function(i){
getKeyValue(keys[i],function(v){
values[keys[i]] = v;
});
})(i);
In the above code, a function is created and then called with i
as a parameter. This means that i
is now part of the scope of the IIFE and cannot be changed by the loop before the callback is called. This trick works outside of code.org as well and is useful for javascript programming in general; however, in those cases, you can use the let
keyword instead of var
and get the intended result.
(pls upvote this, I wanna get all the badges)