在循环中串联XMLHTTPRequest响应,以便在所有循环完成时进行日志记录



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

1'产品名称1,部件编号2342'

2'产品名称2,部件编号8789'

我想在这些响应返回时将它们连接起来,这样,在某个时候,我可以将所有响应记录为一个字符串
我怎样才能做到这一点?

目前,我无法确定是否所有请求都已完成,因此无法记录最终的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);
    }
})();

使用javascript闭包:

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

取自: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。如何处理请求失败取决于您,但希望您现在应该知道如何处理。

命名您的操作,并使用一个公共位置来存储结果,以及完成所有操作时的回调;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);

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

你可以变得更花哨,一次把它们全部发送出去,然后在它们进来的时候订购,但这有点高级。看看Promises,让类似的事情变得相对容易。

最新更新