2016-04-07 3 views
0

Что это даже означает в терминах следующего кода, то res.send прекрасно работает, однако в моей консоли я получаю следующее сообщение:Не удается отправить заголовки после отправки?

http.js:689 
throw new Error('Can\'t set headers after they are sent.'); 

app.get('/summoner/:summonerName', function(req, res) { 
lolapi.Summoner.getByName(req.params.summonerName, function(err, obj) { 
    var options = { 
    beginIndex: 0, 
    endIndex: 1 
    }; 
    lolapi.MatchList.getBySummonerId(obj['savisaar2'].id, options, function(err, matches) { 
    var gameMatches = matches.matches; 
    for(var i = 0; i < gameMatches.length; i++) { 
     lolapi.Match.get(gameMatches[i].matchId, function(err, games) { 
     res.send({profile : obj, matchHistory : games}); 
     }); 
    } 
    }); 
}); 
}); 
+0

Возможный дубликат [Ошибка Node.js: не удается установить заголовки после того, как они отправляются] (http://stackoverflow.com/questions/7042340/node -js-error-cant-set-headers-after-they-are-sent) – JordanHendrix

+0

Вы можете вызвать только 'res .send() 'один раз за запрос. Вы вызываете его несколько раз в цикле. – jfriend00

+0

Какова цель этого кода? Вы вызываете 'lolapi.Match.get()' внутри цикла 'for', а затем пытаетесь выполнить' res.send() 'для каждого' lolapi.Match.get() '. Вызов 'res.send()' более одного раза для данного запроса вызывает причину ошибки. Но как должен работать код? Что вы должны делать со всеми вашими результатами? Вы пытаетесь собрать все результаты вместе, а затем отправить их всем в качестве ответа? – jfriend00

ответ

0

Как я уже объяснял в моих комментариях, вы вызываете res.send() Внутри for, что означает, что вы вызываете его более одного раза. Вы можете вызвать его только один раз за запрос. Вот почему вы видите сообщение об ошибке в консоли.

Это не совсем ясно, что ваш код действительно хочет сделать, но если желание собрать все результаты в массив и отправить их все в качестве ответа, то вы можете сделать это так:

app.get('/summoner/:summonerName', function (req, res) { 
    lolapi.Summoner.getByName(req.params.summonerName, function (err, obj) { 
     if (err) { 
      return res.status(500).end(); 
     } 
     var options = {beginIndex: 0, endIndex: 1}; 
     lolapi.MatchList.getBySummonerId(obj['savisaar2'].id, options, function (err, matches) { 
      var gameMatches = matches.matches; 
      var results = []; 
      for (var i = 0; i < gameMatches.length; i++) { 
       lolapi.Match.get(gameMatches[i].matchId, function (err, games) { 
        if (err) { 
         return res.status(500).end(); 
        } 
        results.push({profile: obj, matchHistory: games}); 
        // if all results are done, then send response 
        if (results.length === gameMatches.length) { 
         res.json(results); 
        } 
       }); 
      } 
     }); 
    }); 
}); 

Примечание: Я также добавил рудиментарную обработку ошибок.

Если вы хотите, чтобы результаты в определенном порядке, что вы просили то, то вы можете добавить немного больше кода, чтобы сделать это так:

app.get('/summoner/:summonerName', function (req, res) { 
    lolapi.Summoner.getByName(req.params.summonerName, function (err, obj) { 
     if (err) { 
      return res.status(500).end(); 
     } 
     var options = {beginIndex: 0, endIndex: 1}; 
     lolapi.MatchList.getBySummonerId(obj['savisaar2'].id, options, function (err, matches) { 
      var gameMatches = matches.matches; 
      var results = new Array(gameMatches.length); 
      var cntr = 0; 
      for (var i = 0; i < gameMatches.length; i++) { 
       (function(index) { 
        lolapi.Match.get(gameMatches[i].matchId, function (err, games) { 
         if (err) { 
          return res.status(500).end(); 
         } 
         ++cntr; 
         results[index] = {profile: obj, matchHistory: games}; 
         // if all results are done, then send response 
         if (cntr === gameMatches.length) { 
          res.json(results); 
         } 
        }); 
       })(i); 
      } 
     }); 
    }); 
}); 

Поскольку Обещания теперь стандарт в 2016 году, вот идея что это может выглядеть следующим образом, используя Bluebird библиотеку обещание:

const Promise = require('bluebird'); 
Promise.promisifyAll(lolapi.Summoner); 
Promise.promisifyAll(lolapi.MatchList); 
Promise.promisifyAll(lolapi.Match); 

app.get('/summoner/:summonerName', function (req, res) { 
    var main; 
    lolapi.Summoner.getByNameAsync(req.params.summonerName).then(function(obj) { 
     main = obj; 
     var options = {beginIndex: 0, endIndex: 1}; 
     return lolapi.MatchList.getBySummonerIdAsync(obj['savisaar2'].id, options); 
    }).then(function(matches) { 
     var gameMatches = matches.matches; 
     return Promise.map(gameMatches, function(item){ 
      return lolapi.Match.getAsync(item.matchId).then(function(games) { 
       return {profile: main, matchHistory: games}; 
      }); 
     }); 
    }).then(function(results) { 
     res.json(results); 
    }).catch(function(err) { 
     res.status(500).end(); 
    }); 
} 
Смежные вопросы