2013-08-17 4 views
0

У меня возникла проблема с кодом моего приложения, и я хотел бы знать, как лучше ее обрабатывать: у меня есть функция, которая применяет 5 значений для обратного вызова, и мне бы хотелось знать лучший способ его использования.Node.js: множественные обратные вызовы от одной функции

Вот мой код функции:

var someFunc = function(callback) { 
var http = require('http'); 
var id; 
var url = 'http://somesite.com/json'; 


// First request to get an array of 5 elements 
http.get(url, function(res) { 
    var body = ''; 

    res.on('data', function(chunk) { 
     body += chunk; 
    }); 

    res.on('end', function() { 
     var jsonResult = JSON.parse(body); 
// 5 requests with a value from each of the 5 elements 
     for (var i=0;i<5;i++) 
     { 
      (function(idx) { 
       gameId = jsonResult.gameList[idx].id; 
       url = 'http://somesite.com' + id + '/token'; 
       http.get(url, function(res) { 
        var body = ''; 

        res.on('data', function(chunk) { 
         body += chunk; 
        }); 

        res.on('end', function() { 
         jsonRes = JSON.parse(body); 
         callback.apply(null, [idx, jsonRes.interestScore]); 
        }); 
       }).on('error', function(e) { 
        console.log("Got error: ", e); 
       }); 
      })(i); 
     } 

    }); 
}).on('error', function(e) { 
    console.log("Got error: ", e); 
}); 
}; 
exports.someFunc = someFunc; 

Когда я вызываю функцию для получения 5 значений Я делаю это так:

exports.featured = function(req, res){ 
    getSome.someFunc(function callback(result) { 
     var variables = {}; 
     var variableName = result; 
     variables[variableName] = jsonRes.interestScore; 
     res.render('featured', { score0: variables[0], score1: variables[1], score2: variables[2], score3: variables[3], score4: variables[4] }); 
    }); 
}; 

К сожалению «res.render» вызывается после того, функция получает только 1 значение, поэтому я хочу знать, как это сделать, или сделать правильный обратный вызов.

Спасибо.

ответ

0

Первая проблема, которую я вижу, заключается в том, что вы назначаете слушателю событие end событий пять раз. Вы должны сделать это только один раз. Вы можете получить результат пять раз и после этого вызвать обратный вызов. Вот пример, который использует модуль запроса:

var request = require('request'); 

var makeRequests = function(callback) { 
    var result = [], 
     done = 0; 
    request('http://www.google.com', function (error, response, body) { 
     if (!error && response.statusCode == 200) { 
      // read the body here 
      var searchFor = [ 
       'nodejs',  // 1 
       'http request', // 2 
       'npm',   // 3 
       'express',  // 4 
       'javascript' // 5 
      ]; 
      for(var i=0; keyword = searchFor[i]; i++) { 
       request('https://www.google.bg/search?q=' + keyword, function (error, response, body) { 
        if (!error && response.statusCode == 200) { 
         result.push(body); 
         ++done; 
         if(done == searchFor.length) { 
          callback(result); 
         } 
        } 
       }); 
      } 
     } 
    }); 
} 

makeRequests(function(result) { 
    console.log("result=" + result.length); 
}) 
+0

извини, я забыл упомянуть, что цикл играет важную роль в моем коде, он используется, чтобы сделать HTTP GET запрос. Я отредактирую свой пост с полным кодом функции, чтобы быть более четким. – user2663041

+0

Хорошо, я понимаю, но вставку слушателя внутри цикла - это не очень хорошая идея. Это приведет к неожиданным результатам, потому что у вас есть много функций, вызываемых этим событием * end * – Krasimir

+0

Да, я понимаю, этого я и пытался избежать, и почему я спросил здесь. – user2663041

1

Функция вы звоните в асинхронном, ответ end события могут происходить в любое время. И ваш код вызывает res.render для выполнения 5 раз, но вам нужно всего лишь выполнить 1 раз с 5 значениями. Вы должны использовать модуль, такой как async, который поможет вам запустить несколько задач и выполнить обратный вызов, когда все они будут завершены.

Пример:

var jsonResult = JSON.parse(body); 
var arr = []; 
for(var i = 0; i < 5; i++){ 
    arr.push(jsonResult[0].interestScore); 
} 
async.map(arr, myAsyncFunction, function(err, results){ 
    // results[0] => response of first index 
    // results[4] => response of last index 
}); 
Смежные вопросы