【问题标题】:asychronous function in loop javascript nodejs循环javascript节点js中的异步函数
【发布时间】:2015-07-15 22:11:39
【问题描述】:

我需要扫描行程数组并计算当前行程与数组中每个行程之间的行程时间并选择最短的行程。对于计算,我需要发送谷歌地图 api 调用。

我对异步回调函数很困惑。 谁能帮我解决如何在 for 循环中发送 api 调用并检查结果并继续?

谢谢。

行程在我的数组列表中;

数组:

array=[trip1,trip2, trip3,....];

JS:

function assigntrips(array){

var triplist = [];
for(var i=0; i< array.length; i++){

        var fstnode = array[i];
        for(var j=i+1; j<array.length; j++){
            //here i want to get the response from google api and decide if i want to choose the trip. 
           if not the for loop continues and send another api call.

        }

    }
}


function apicall(inputi, cb){
var destination_lat = 40.689648;
var destination_long = -73.981440;


var origin_lat = array[inputi].des_lat;
var origin_long = array[inputi].des_long;

var departure_time = 'now';

    var options = { 
            host: 'maps.googleapis.com',

            path: '/maps/api/distancematrix/json?origins='+ origin_lat    +','+origin_long+ '&destinations=' + office_lat + ',' + office_long + '&mode=TRANSIT&departure_time=1399399424&language=en-US&sensor=false'

        }

 http.get(options).on('response',function(response){
        var data = '';

        response.on('data',function(chunk){
            data += chunk;
        });
        response.on('end',function(){
            var json = JSON.parse(data);
            console.log(json);
            var ttltimereturnoffice = json.rows[0].elements[0].duration.text;
        //var node = new Node(array[i],null, triptime,0,ttltimereturnoffice,false); 
        //tripbylvtime.push(node);
        cb(ttltimereturnoffice + '\t' + inputi);
        });


        });

}

【问题讨论】:

    标签: javascript json node.js google-maps httprequest


    【解决方案1】:

    您无法检查循环中的结果。循环在过去,回调发生在未来——你无法改变它。你只能做两件事,一件是对另一件的抽象:

    1) 您可以创建回调,使其收集结果并在所有结果都存在时进行比较。

    2) 你可以使用 Promise 来做同样的事情。

    #1 方法看起来像这样(同时适当地修改代码中的 cb 调用):

    var results = [];
    function cb(index, ttltimereturnoffice) {
      results.push([index, ttltimereturnoffice]);
      if (results.length == array.length) {
        // we have all the results; find the best one, display, do whatever
      }
    }
    

    我不太清楚你正在使用什么库,以及它是否支持承诺,但如果http.get 返回一个承诺,你可以通过将承诺收集到一个数组中来执行 #2,然后使用承诺库的 @987654324 @ 或when 或类似的附加回调在所有gets 正在完成。

    【讨论】:

    • 如果我想使用数组中的元素并将其发送到 api,然后检查第一个 api 响应,然后决定是否要发送带有数组中下一个元素的另一个 api,我可以不这样做?
    • @ChloéLinHe 您可以这样做,但需要将请求链接到回调。 function cb(){if(test){doAnotherQuery()}}doAnotherQuerycb 回调。
    • 哦,对不起,我没有从你的问题中理解这一点。你当然可以这样做;但在这种情况下,你不能使用循环。我稍后会草拟一个答案。编辑:@bcdan 说得对。
    • @bcdan 谢谢,那么当我认为我完成了内循环中的 api 调用时,我该如何停止并返回外循环?
    • @amadan 谢谢。我正在尝试学习如何使用承诺。但这很令人困惑。你能举例说明如何在循环中使用promise吗?我正在使用 nodejs,我认为它支持 promise,否则我可以使用 promise api 或 q 库
    猜你喜欢
    • 2021-09-11
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-07-09
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多