Search code examples
javascriptarraysangularjsasynchronousangular-translate

How to assign an array when calling asynchronous functions?


I'm using AngularJS and Angular Translate. I have an array of objects that have 'key' property - a string that should be translated.

This is my array of objects:

var objects = [{
        id: 1,
        key: 'Jacket'
    }, {
        id: 2,
        key: 'Trousers'
    }, {
        id: 3,
        key: 'Hat'
    }];

These are my translations:

var translationsEN = { 
    Jacket: 'This is Jacket in English',
    Trousers: 'This is Trousers in English',
    Hat: 'This is Hat in English'
}

When some particular events occur I need an array of the objects but with the translations, not with the keys. That's why I have a function that does the following:

var translatedObjects = [];

for (var i = 0; i < objects.length; i++) {
    $translate(objects[i].key).then(function (translation) {
        translatedObjects[i] = translation;
    });
} 

After the function execution the result stored in the translatedObjects array is:

[null,null,null,"This is Hat in English"]

I guess that this is happening because I'm actually executing an asynchronous call to the $translate service and translatedObject[i] is not actually pointing to the right object, because 'i' is not defined in the current context.

So, how can I execute an asynchronous function call and assign my array appropriately as shown in the example above?


Solution

  • Yes, the for loop will have completed and the value of i will be 3 when the callback fires. The three callbacks will then overwrite the value at the same index three times.

    You can encapsulate your variable in a new scope:

    for (var i = 0; i < objects.length; i++) {
        $translate(objects[i].key).then((function(x) { 
            return function (translation) {
               translatedObjects[x] = translation;
            };
        })(i));
    } 
    

    What happens above is you create an anonymous function that accepts a parameter, x, and returns a callback function. So when you call that function passing i=0, it will return a callback function which has access to x=0 from the scope in which it was created. At the next iteration, the anonymous function will be called again, and return a new callback function, where x is 1, etc.

    If you know that the callbacks will be called sychronously, and assigning to an array is all you want to do, then ngLover's answer is probably more readable.