当循环内的服务调用正在等待promise时,Angular.JS循环继续运行

时间:2017-02-13 20:36:06

标签: angularjs callback angular-promise q

“AddDistance”是DB函数的插入, 问题是hash [k] [2]值随循环跳转而“distance”(服务承诺)仍在等待,结果我向我的DB插入了错误的行。

如何在“AddDistance()”运行之前保持循环跳转到下一个对象,我应该使用Q $,while,.then()吗?

我尝试了上述但失败了,可能没有正确地做到。

请告知......

sql("""SELECT CAST(dayToInt(date_format(dateEst, 'EEEE')) AS float) AS dayOfWeekInt 
FROM data""")

2 个答案:

答案 0 :(得分:1)

通过将promises链接在一起而不是并行运行,可以确保长时间运行的操作一次运行一个。需要注意确保参数正确传递,因为循环将在任何长时间运行的函数被调用之前完成。

因为函数按顺序执行,所以可以将结果存储在数组中并确保它们按顺序排列。

var promise = $q.resolve();
var distances = [];

for (var k in hash) {
    promise = chainPromise(promise, callGoogleMaps, k);
};

promise.then(function () {
    console.log('forEach loop completed. Do Something after it...',
      distances);
});

function chainPromise(promise, fn, k) {
    return promise.then(function() { return fn(k); });
}

function callGoogleMaps(k) {
    return $q(function(resolve) {
       //sample of a long-running operation inside loop...
       GoogleMaps(hash[k][0], hash[k][1], function (x) {
         var distance = x.rows[0].elements[0].distance.value;
         distance = parseInt(distance / 1000);
         AddDistance({ CityID1: hash[k][2], CityID2: $scope.CompanyCity.Id, DistanceKM: distance });
         console.log(distance);
         distances.push(distance);
         resolve();
       });
    });
}

答案 1 :(得分:0)

你可以做类似下面的事情,但它不会保持循环:

var loopPromises = [];
var distanceList = [];

for (var k in hash) {
    var deferred = $q.defer();
    loopPromises.push(deferred.promise);
    //sample of a long-running operation inside loop...
    distanceList[k] = GoogleMaps(hash[k][0], hash[k][1], function (x) {
        var distance = x.rows[0].elements[0].distance.value;
        distance = parseInt(distance / 1000);
        AddDistance({ CityID1: hash[k][2], CityID2: $scope.CompanyCity.Id, DistanceKM: distance });
        console.log(distance);
        //return distance;
        deferred.resolve(distance);
    });    
};

$q.all(loopPromises).then(function () {
    console.log('forEach loop completed. Do Something after it...');
    //use the distanceList here
});

请注意,只要下一次迭代不依赖于前一次迭代,这种方法就可以正常工作。