2013-08-17 37 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

我看到的第一個問題是,您正在爲結尾事件分配聽衆五次。你應該只做一次。您可以收集結果五次,然後再調用回調。下面是使用請求模塊的例子:

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次,但你只需要它用5個值執行1次。你應該使用一個像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 
});