2016-05-24 4 views
2

У меня возникли проблемы с созданием HTTP-запроса внутри цикла.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; 
      } 
}); 

Я надеюсь, что было ясно с вопросом.

+0

См. Http: // stackoverflow.com/questions/750486/javascript-clos-inside-loops-simple-practice-example –

ответ

5

Проблема здесь одна из области 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){...}.

Что это означает, что этот цикл продолжает выполнять и цикл в то время как запрос делается, то есть, если запрос не достаточно быстро, current будет обновлять и отличаться, когда запрос возвращается, и так будут переменные цикла цикла.


Решение, с которым я столкнулся в этом вопросе, - это функция, определяющая внутренний запрос в цикле 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 в свою область.

+0

I'v попробовал, как вам было предложено, но похоже, что он не видит цикл for, программа выполняет строку непосредственно перед и затем он останавливается. Я не могу понять, почему. – Mirko

+0

Редактировать: Решено! По какой-то неизвестной причине я написал плохой цикл for, инкрементная часть была вторым аргументом, а не последним. Я чувствую себя глупо сейчас, спасибо за помощь! – Mirko

+0

Просто видел ваши комментарии, рад узнать, что я мог бы помочь! Дайте мне знать, если у вас есть еще вопросы. – Aeolingamenfel

0

Вы забыли использовать переменные цикла i и j. Приведенный выше код будет продолжать делать запросы с телом [0] как src и body [1] как dest для продолжительности цикла, в котором тело имеет длину> = 2. Попробуйте использовать https://github.com/caolan/async#forEachOf или https://github.com/caolan/async#each для вызова функций async в цикле.

+0

Да, это была ошибка копирования и вставки, очевидно, что переменными являются body [i] и body [j + 1], я редактирую в вопрос, спасибо :) – Mirko

+0

Я считаю, что асинхронный модуль caolan очень полезен при одновременном вызове большого количества асинхронных функций. –

Смежные вопросы