在循环中连接XMLHTTPRequest响应以在所有循环完成时记录

时间:2014-09-15 23:38:25

标签: javascript

json.orderItem.length == 2,因此解雇了2 HTTP个请求 如果我一个接一个地发出这两个请求(不是循环),我会收到这两个单独的响应:

1' productName1,partNumber2342'

2' productName2,partNumber8789'

我想在返回时连接这些响应,所以在某些时候,我可以将所有响应记录为单个字符串。
我怎么能做到这一点?

目前,我无法确定所有请求是否已完成,因此请记录最终String

包裹在循环中的请求..

var f = (function(){
    var xhr = [];
    var test = '';
    for (i = 0; i < json.orderItem.length; i++){
        (function (i){
            xhr[i] = new XMLHttpRequest();
            url = '/products/byId/' + json.orderItem[i].productId;
            xhr[i].open("GET", url, true);
            xhr[i].onreadystatechange = function () {
                if (xhr[i].readyState == 4 && xhr[i].status == 200) {
                    test += JSON.parse(xhr[i].responseText).entry[0].name + ', ' + JSON.parse(xhr[i].responseText).entry[0].partNumber;
                }
            };
            xhr[i].send();
        })(i);
    }
})();

2 个答案:

答案 0 :(得分:1)

使用javascript闭包:

  

闭包是指独立(自由)变量的函数。换句话说,闭包中定义的函数会记住&#39;它创建的环境。

取自:https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Closures

闭包在Javascript中是一个非常强大的概念,因此如果您不熟悉它,我建议您继续阅读。

现在我们如何使用它来解决您的问题?

var f = (function() {
    // scope a
    var xhr = [],
        successfulRequests = 0,
        responseString = "";

    for (i = 0; i < json.orderItem.length; i++){
        (function (i) {
            xhr[i] = new XMLHttpRequest();
            url = '/products/byId/' + json.orderItem[i].productId;
            xhr[i].open("GET", url, true);
            xhr[i].onreadystatechange = function () {
                if (xhr[i].readyState == 4 && xhr[i].status == 200) {
                    // scope b

                    // track successful requests here
                    successfulRequests++;                   // "remembered" through closure
                    responseString += xhr[i].responseText;  // "remembered" through closure

                    if(successfulRequests == json.orderItem.length) {
                        console.log(responseString);
                    }
                }
            };
            xhr[i].send();
        })(i);
    }
})();

在scopeA中声明的变量通过闭包在scopeB中记住。

注意:此实现仅在所有请求成功完成后记录responseString。您希望如何处理请求失败取决于您,但希望您现在应该知道如何执行此操作。

答案 1 :(得分:0)

命名您的操作并使用公共位置来存储结果,并在完成所有操作时使用回调; alert()用于这个简单的例子:

var test = '';
function grab(i, done){
        var xhr = new XMLHttpRequest(),
        url = '/products/byId/' + json.orderItem[i].productId;
        xhr.open("GET", url, true);
        xhr.onload= function () {
                var ob=JSON.parse(xhr.responseText);
                test += ob.entry[0].name + ', ' +ob.entry[0].partNumber;
                if(json.orderItem[i+1]){ //more items, pass forward:
                      grab(i+1, done); 
                }else{ //no more, run run done()
                      done(test);
                }
        };
        xhr.send();
}//end grab
grab(0, alert);

您可能希望更多地抽象它以传递集合或结果列表以使其更易于重复使用,但可以使用相同的基本步骤序列来保持异步操作中的顺序。

你可以变得更加漂亮,并立即将它们全部发送出去,并在它们进来时订购它们,但这更加先进。看看Promise这样做的东西比较容易。