2015-07-10 3 views
0

Я использую Step для управления параллельными запусками. То, что я пытаюсь сделать, это:Nodejs - многократные обратные вызовы

  1. Прочитайте файл JSON с помощью HTTP (файл в формате JSON содержит массив событий)
  2. Loop массив событий и получить детали событий, используя HTTP
  3. Хранить информацию о событии в локальных переменных «событиях»

Что я делаю, как это коснуться:

var events = []; // this is the local variable to hold event details 
 
Step(
 
\t function getEvents(){ 
 
\t \t 
 
\t \t var options = { 
 
\t \t \t host: '95.85.14.142', 
 
\t \t \t port: 80, 
 
\t \t \t path: '/data/IT/config.json', 
 
\t \t \t method: 'GET' 
 
\t \t }; 
 
\t \t 
 
\t \t http.request(options,this).end(); 
 
\t 
 
\t }, 
 
\t function getEventsResponse(res){ 
 
\t \t 
 
\t \t if (res.statusCode==200){ 
 
\t \t \t \t 
 
\t \t \t res.setEncoding('utf8'); 
 
\t \t \t res.on('data',this); 
 
\t \t \t 
 
\t \t } 
 
\t }, 
 
\t function getEventDetails(data){ 
 
\t \t 
 
\t \t var events = JSON.parse(data).events; 
 
\t \t 
 
\t \t var group = this.group(); 
 
\t \t for(e in events){ 
 
\t \t \t var event = events[e]; \t 
 
\t \t \t var options = { 
 
\t \t \t \t host: '95.85.14.142', 
 
\t \t \t \t port: 80, 
 
\t \t \t \t path: '/data/IT/events/'+event.code+'.json', 
 
\t \t \t \t method: 'GET' 
 
\t \t \t }; 
 
\t \t \t 
 
\t \t \t http.request(options,group()).end(); 
 
\t \t 
 
\t \t } \t 
 
\t 
 
\t }, 
 
\t function getEventDetailsResponse(err,responses){ 
 
\t \t 
 

 
\t \t // responses = [undefined,undefined,..] ??? 
 

 
\t \t 
 
\t }, 
 
\t ... 
 
);

В getEventDetailsResponse Я ожидаю, что массив объектов, но я получаю массив неопределенных переменных:

[неопределенная, неопределенная, ..]

Что я делаю неправильно?

ответ

1

Вот рабочая версия вашего кода, которая заканчивается распечаткой переменной событий. Ниже я расскажу подробности.

var http = require('http'); 
var Step = require('step'); 

var events = []; // this is the local variable to hold event details 
Step(
    function getEvents(){ 
     var options = { 
      host: '95.85.14.142', 
      port: 80, 
      path: '/data/IT/config.json', 
      method: 'GET' 
     }; 
     http.request(options,this).end(); 
    }, 
    function getEventsResponse(res){ 
     if (res.statusCode==200){ 
      res.setEncoding('utf8'); 
      res.on('data',this); 
     } 
    }, 
    function getEventDetails(data){ 
     var events = JSON.parse(data).events; 
     var group = this.group(); 
     for(e in events){ 
      var event = events[e]; 
      var options = { 
       host: '95.85.14.142', 
       port: 80, 
       path: '/data/IT/events/'+event.code+'.json', 
       method: 'GET' 
      }; 

      (function(){ 
       var generated_callback = group(); 
       http.request(options,function(res){generated_callback(null,res);}).end(); 
      })(); 
     } 
    }, 
    function getEventDetailsResponse(err,responses){ 
     var group = this.group(); 
     for(i in responses){ 
      var r = responses[i]; 
      if (r.statusCode==200){ 
       r.setEncoding('utf8'); 
       (function(){ 
        var generated_callback = group(); 
        r.on('data',function(data){ 
         var parsed_data = JSON.parse(data); 
         events.push(parsed_data); 
         generated_callback(null,parsed_data); 
        }); 
       })(); 
      } 
     } 
    }, 
    function displayEvents(err,passed_events){ 
     console.log("Events Global Variable"); 
     console.log(events); 
     console.log("Passed Events"); 
     console.log(passed_events); 
    } 
); 

Это возвращает:

Events Global Variable 
[ { title: 'TITLE 1' }, 
    { title: 'TITLE 2' }, 
    { title: 'TITLE 3' } ] 
Passed Events 
[ { title: 'TITLE 1' }, 
    { title: 'TITLE 2' }, 
    { title: 'TITLE 3' } ] 

вопрос вы запускали в, который я должен был вырыть в код Шаг, чтобы выяснить, является то, что групповой метод() генерирует обратный вызов, который ожидает, первый аргумент должен быть (возможно, нулевым) объектом ошибки, а второй - фактическим ответом/данными. http.request только передает объект ответа назад, и Step интерпретировал это как ошибку.

Чтобы обойти это, вы можете вручную вызвать групповую функцию для генерации вашего обратного вызова, а затем вручную вызвать обратный вызов с нулевым первым аргументом. Так как это все асинхронно, вам придется обернуть это в закрытие самозапуска, чтобы изолировать и продолжить созданный обратный вызов, иначе он будет перезаписываться каждый раз, и когда первый запрос вернется, он попытается вызвать обратный вызов, который был сгенерированный для третьего - или любого другого - запрос вместо его собственного. Вы можете видеть, что это обернуто вокруг http.request в моей версии функции getEventDetails, а также немного более сложный пример в функции getEventDetailsResponse.

В качестве примечания стороны переменная событий, объявленная в верхней части скрипта, является глобальной переменной, а не локальной. То, что объявлено в getEventDetails, является локальной переменной. Если вы хотите установить данные в глобальную переменную с помощью var events = JSON.parse(data).events;, вы можете сделать это, удалив «var» из этой строки.

+0

По-прежнему не получается заставить его работать ... – Franz

+0

Возможно, я немного сбил вас с пути. Я отредактирую ответ с рабочей версией вашего скрипта. –