如何在调用异步函数时分配数组?

时间:2015-11-20 07:35:07

标签: javascript arrays angularjs asynchronous angular-translate

我正在使用AngularJS和Angular Translate。我有一个具有'key'属性的对象数组 - 一个应该被翻译的字符串。

这是我的对象数组:

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

这些是我的翻译:

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

当某些特定事件发生时,我需要一个对象数组,但需要翻译,而不是键。这就是为什么我有一个执行以下功能的功能:

var translatedObjects = [];

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

执行函数后,存储在translatedObjects数组中的结果为:

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

我猜这种情况正在发生,因为我实际上正在执行对$ translate服务的异步调用,而translateObject [i]实际上并没有指向正确的对象,因为'i'没有在当前上下文中定义。

那么,如何执行异步函数调用并正确分配我的数组,如上例所示?

3 个答案:

答案 0 :(得分:1)

您可以使用push数组方法插入数据。不需要传递i,因为它将以相同的顺序插入。

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

答案 1 :(得分:1)

是的,当回调触发时,for循环将完成,i的值将为3。然后三个回调将覆盖相同索引的值三次。

您可以将变量封装在新范围中:

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

上面的内容是创建一个接受参数x的匿名函数,并返回一个回调函数。因此,当您调用该函数传递i=0时,它将返回一个回调函数,该函数可以从创建它的作用域访问x=0。在下一次迭代中,将再次调用匿名函数,并返回一个新的回调函数,其中x为1,等等。

如果您知道将同步调用回调,并且只想分配给数组,那么ngLover的答案可能更具可读性。

答案 2 :(得分:0)

您已使用承诺,因此可以使用Promise.all()

var promises = [];
for (var i = 0; i < objects.length; i++) {
    promises.push($translate(objects[i].key));
}

Promise.all(promises).then(function (translatedObjects) {
    // use your array here
});