【问题标题】:Http request inside a loop循环内的 Http 请求
【发布时间】:2016-05-24 18:30:53
【问题描述】:

我在循环内发出 HTTP 请求时遇到了一些麻烦。

让我解释一下我有什么......

我创建了一个 http GET 来检索一些值,然后我需要为我刚刚从第一个请求中获取的每一对值创建另一个 HTTP GET。

这两个调用都可以,如果我切断for 循环并尝试运行整个请求链,它可以完美运行,但自从我删除循环以来只有一次。我怎样才能让它发挥作用?

代码如下:

request({
url: "some_url",
    method: "GET",
    json:true,
    headers:[{'content-type': 'application/json'}]
    }, function (error, response, body){
            if(!error & response.statusCode === 200){           
                for(var i=0;i<body.length;i++){
                    for(var j=i;j<body.length-1;j++){
                        //if(i === body.length-1) return;
                        src = body[i].name;
                        dest = body[j+1].name;
                        console.log("sorgente ",sorg);

                        request({
                            url: "https://maps.googleapis.com/maps/api/distancematrix/json?origins="+src+"&destinations="+dest,
                            method: "POST",
                            json:true,
                            headers:[{'content-type': 'application/json'}]
                        }, function (error, response, body){
                            if(!error & response.statusCode === 200){
                                console.log("TIME ",body.rows[0].elements[0].duration.text);
                                return;
                            }else{
                                console.log("google API failed!: ");
                                return;
                            }
                        }); 

                    }
                }

            }else{
                console.log("/google_api failed!: ");
                return;
            }
 });

我希望我对这个问题很清楚。

【问题讨论】:

标签: javascript node.js http-request


【解决方案1】:

这里的问题是 Javascript 范围和拼写错误之一。

首先,您硬编码了body[0]body[1] 的数组索引。看起来您的意思是让它们成为循环变量。

其次,用简化的伪 JavaScript 概述您的范围问题:

var requestList = [...];

for(var i = 0; i < requestList.length; i++){
    var current = requestList[i];

    // make a request based on current or the data
    // in current. 
    request(..., function(result){
        // do something with the current variable
        current.foo = result.bar;
    });
}

所有网络请求都是异步的。曾经有一种方法可以强制它们同步运行,但在大多数主流浏览器中已被弃用。这意味着发出请求,并且可能会在实际代码之外得到响应,,然后调用某种回调——在这种情况下,匿名内部函数function(result){...}

这意味着 for 循环在发出请求时继续执行并循环,这意味着如果请求不够快,current 将在request 会返回,for 循环变量也会返回。


我为这类事情遇到的解决方案是在 for 循环中确定内部请求的范围。

不是直接在 for 循环中发出新请求,而是将它移到它自己的函数中:

var requestList = [...];

for(var i = 0; i < requestList.length; i++){
    var current = requestList[i];

    GetMyResourceData(current);
}

function GetMyResourceData(current){
    request(..., function(result){
        // do something with the current variable
        current.foo = result.bar;
    });
}

每次调用GetMyResourceData 函数时,都会为该函数创建一个新作用域,因此当您到达回调时,该函数中的current 变量会被保留。

所以,这就是我建议您对代码执行的操作。将 for 循环之外的第二个请求移到它自己的范围内。

【讨论】:

  • 我已经按照您的建议进行了尝试,但似乎没有看到 for 循环,程序在 for 之前执行该行,然后停止。我不知道为什么。
  • 编辑:已解决!由于某些未知原因,我将 for 循环写得不好,增量部分是作为第二个参数而不是最后一个参数。我现在觉得很愚蠢,感谢您的帮助!
  • 刚看到你们的cmets,很高兴知道我能帮上忙!如果您有任何其他问题,请告诉我。
  • 很好的答案!也为我工作!
  • 很好,节省了我数小时的搜索时间。
【解决方案2】:

您是否忘记使用循环变量 i 和 j。上面的代码将在循环期间继续以 body[0] 作为 src 和 body[1] 作为 dest 发出请求,前提是 body 的长度 >= 2。 尝试使用https://github.com/caolan/async#forEachOfhttps://github.com/caolan/async#each 在循环中调用异步函数。

【讨论】:

  • 是的,这是复制粘贴的错误,显然变量是body[i]和body[j+1],我在问题中编辑,谢谢:)
  • 我发现caolan的异步模块在并行调用大量异步函数时非常有用
猜你喜欢
  • 2020-05-09
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-10-16
  • 1970-01-01
相关资源
最近更新 更多