簡體   English   中英

異步請求進入for循環angular.js

[英]Async request into for loop angular.js

我有一個數組,我需要逐個通過http post請求將數組的值發送到webservice。 對於node.js,我正在使用“async”包為ex: async.eachSeries做得很好,我怎么能為angular.js做同樣的事情,我的正常異步代碼;

//this code sends all queries of array (maybe  5.000 request at same time , it is hard to process for webservice :=) ) at same time and wait for all responses. 
//it works but actually for me , responses should wait others at end of loop should work one by one 
//like async.eachSeries module!

    for (var i = 0; i < myArr.lenght; i++) {
        (function (i) {
                var data = {
                    "myQuery": myArr[i].query
                };
                $http.post("/myServiceUrl", data).success(function (result) {
                    console.log(result);
                });
        })(i);
}

Matt WayChris L都回答正確 ,您可以調查Chris的答案,以了解for循環中異步同步函數。

您可以通過將promises鏈接在一起來使用$q來創建類似的需求。 例如:

var chain = $q.when();
angular.forEach(myArr, function(item){
    chain = chain.then(function(){
        var data = {
            myQuery: item.query
        };
        return $http.post('/myServiceUrl', data).success(function(result){
            console.log(result);
        });
    });
});

// the final chain object will resolve once all the posts have completed.
chain.then(function(){
    console.log('all done!');
});

基本上,只要前一個承諾完成,您就會運行下一個承諾。 這里強調的是,根據您的問題,每個請求都將等到上一個請求完成。

如果我正確理解你的問題。 您希望以同步方式運行for循環,以便下一次迭代僅在上一次迭代完成后發生。 為此,您可以使用同步循環/回調。 特別是如果訂單很重要。

        var syncLoop = function (iterations, process, exit) {
            var index = 0,
                done = false,
                shouldExit = false;
            var loop = {
                next: function () {
                    if (done) {
                        if (shouldExit && exit) {
                            return exit(); // Exit if we're done
                        }
                    }
                    // If we're not finished
                    if (index < iterations) {
                        index++; // Increment our index
                        process(loop); // Run our process, pass in the loop
                        // Otherwise we're done
                    } else {
                        done = true; // Make sure we say we're done
                        if (exit) exit(); // Call the callback on exit
                    }
                },
                iteration: function () {
                    return index - 1; // Return the loop number we're on
                },
                break: function (end) {
                    done = true; // End the loop
                    shouldExit = end; // Passing end as true means we still call the exit callback
                }
            };
            console.log('running first time');
            loop.next();
            return loop;
        }

對於您的特定實現:

    syncLoop(myArray.length, function (loop) {
        var index = loop.iteration();
        var data = {
            "myQuery": myArray[index].query
        };
        $http.post("/myServiceUrl", data).success(function (result) {
            console.log(result);
            loop.next();
        });
    }, function () {
        console.log('done');
    });

如果您打算在返回數據后執行某些操作(例如執行計算),則可以使用此方法執行此操作,因為您將按指定的順序返回數據。

我在我構建的統計計算Web應用程序中實現了類似的功能。

編輯:

為了說明我在使用$ q時遇到的問題。當我設置一個小提琴時。 希望這有助於說明我為什么這樣做。

https://jsfiddle.net/chrislewispac/6atp3w8o/

使用Matt的答案中的以下代碼:

var chain = $q.when(promise.getResult());
    angular.forEach(myArr, function (item) {
        chain = chain.then(function () {
            $rootScope.status = item;
            console.log(item);
        });
    });

    // the final chain object will resolve once all the posts have completed.
    chain.then(function () {
        console.log('all done!');
    });

這個小提琴就是我解決方案的一個例子:

https://jsfiddle.net/chrislewispac/Lgwteone/3/

將$ q版本與我的版本進行比較。 查看控制台並想象那些被傳遞到用戶界面以供用戶干預過程和/或對順序返回執行統計操作。

您將看到它不會在控制台中或在Matt的答案視圖中依次給出數字1,2,3,4等。 它“批量”響應然后返回它們。 因此,如果不根據步驟2中的響應運行步驟3,則至少在所提供的答案中,沒有在這里中斷或明確控制同步操作的方法。 當嘗試執行順序計算和/或允許用戶控制斷點等時,這會出現嚴重問題。

現在,我正在挖掘$ q庫和Q庫,看看是否有更優雅的解決方案來解決這個問題。 但是,我的解決方案確實按照要求工作,並且非常明確,這允許我將函數放在服務中並根據我的意願操作某些用例,因為我完全理解它在做什么。 對我來說,這比使用庫更重要(至少在我作為程序員開發的這個階段,我確信在StackOverflow的同一階段還有很多其他人)。

function logResultFromWebService(value)
{
    $http.post("/myServiceUrl", value).success(console.log);
}

angular.forEach(myArray, logResultFromWebService);

如果訂單與發送它們無關緊要

var items = [/* your array */];
var promises = [];
angular.forEach(items, function(value, key){
    var promise = $http.post("/myServiceUrl", { "myQuery": value.query });
    promises.push(promise);
});
return $q.all(promises);

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM