在向前迭代之前等待调用函数完成

时间:2015-10-29 16:29:38

标签: javascript jquery angularjs

关于我必须编写的代码,我在这里有点绑定。 目前我正在尝试迭代一串字符串。找到某个文本后,如果值为true,则该值绑定到temporaryObject.img。之后,必须对服务器进行调用,以便检索某些信息并将其绑定到与第二个属性(temporaryObject.url)相同的temporaryObject。不幸的是,调用可能在迭代完成后解决,因为它没有添加这个添加从调用到Object中的服务器的url。我使用的库是angularjs和jquery。

这是我写的代码的一部分。

$scope.Data = [];
var strArray = ["img1", "link", "img2", "link2", "img3", "link3"];
var re1 = /<img/;
for(var i = 0 ; i < strArray.length ; i++) {
    var tempObject = {};
    var test = re1.test(strArray[i]);
    if (test){
    tempObject.img = strArray[i + 1];
    myAngularService.getServerInformation().then(function(result){
        tempObject.url = result;
        $scope.Data.push(tempObject);
    }
   }

不幸的是,来自服务器的信息没有在迭代完成的同时到达或出现问题,因为$ scope.Data将不包含从服务器请求的url。任何建议如何使用这种代码的承诺将不胜感激。我试着搜索每一个可能的解决方案,但没有用。

1 个答案:

答案 0 :(得分:1)

Javascript是功能范围的。换句话说:

if (true) {
    var testing = 5;
}
console.log(testing); // Logs 5

将此应用于您的示例,tempObject回调函数中的.then都引用了相同的变量!

一种解决方案是在for语句中使用Immediately-Invoked Function Expression(IIFE)来创建新范围:

for(var i = 0 ; i < strArray.length ; i++) {
    (function() {
        var tempObject = {}; // Is now declared within the new function
        /* ... code here ... */
    })();
}

另一种解决方案是简单地使用$.each(或angular.forEach):

$.each(strArray, function(index, value) {
    var tempObject = {}; // Is now declared within the new function
    /* ... code here ... */
}); 

关于等待所有通话结束,一种解决方案是将您的承诺存储在数组中使用有角度的$q服务:

$scope.Data = [];
var promises = [];
var strArray = ["img1", "link", "img2", "link2", "img3", "link3"];
var re1 = /img/;
$.each(strArray, function (index, value) {
    var tempObject = {};
    var test = re1.test(value);
    if (test) {
        tempObject.img = strArray[index + 1];

        var myPromise = myAngularService.getServerInformation();

        myPromise.then(function (result) {
            tempObject.url = result;
            $scope.Data.push(tempObject);
        }

        promises.push(myPromise);
    }
})

$q.all(promises).then(function() {
    // All calls will have finished
    console.log($scope.Data); 
}, function() {
    // At least 1 call failed!
    console.log("an error occurred!");
});