【问题标题】:Express - Error: Can't set headers after they are sent.Express - 错误:发送后无法设置标题。
【发布时间】:2018-04-03 04:42:15
【问题描述】:

当我使用 siege siege -b -r 1 -c 100 https://*****/RTC/stats/rank 测试我的应用程序时

我在我的 nodeJS 控制台中收到此错误

_http_outgoing.js:491
    throw new Error('Can\'t set headers after they are sent.');
    ^

Error: Can't set headers after they are sent.
    at validateHeader (_http_outgoing.js:491:11)
    at ServerResponse.setHeader (_http_outgoing.js:498:3)
    at ServerResponse.header (/home/nodeJS/RTC-stats/node_modules/express/lib/response.js:767:10)
    at ServerResponse.send (/home/nodeJS/RTC-stats/node_modules/express/lib/response.js:170:12)
    at ServerResponse.json (/home/nodeJS/RTC-stats/node_modules/express/lib/response.js:267:15)
    at ServerResponse.send (/home/nodeJS/RTC-stats/node_modules/express/lib/response.js:158:21)
    at Request._callback (/home/nodeJS/RTC-stats/server.js:46:14)
    at Request.self.callback (/home/nodeJS/RTC-stats/node_modules/request/request.js:186:22)
    at emitTwo (events.js:126:13)
    at Request.emit (events.js:214:7)

在这里你可以找到我使用的代码:

const request = require('request');
const express = require('express');

const app = express();

let players = [
  "df6c767a-c4a9-4a42-bbbc-e34c7b4f1e16",
  "22366c4f-744a-422b-81ff-e21608dd5950",
  "c553f6b4-da31-4879-88a6-5dfa28cae1ac",
  "5e5cfb2e-29a5-407e-972b-9999fcd567af",
  "5fcc4c0e-13ca-49d2-a949-b74ef17d146f",
  "094fd818-f794-404c-a2a4-674d3be5e7d3",
];
let responses = [];

let completed_requests = 0;

app.get('/RTC/stats/rank', function (ereq, eres) {
  for (var i = 0, len = players.length; i < len; i++) {
    var playerUUID = players[i];
    var options = {
      url: 'https://r6db.com/api/v2/players/' + playerUUID + '?platform=PC',
      headers: {
        'x-app-id': '5e23d930-edd3-4240-b9a9-723c673fb648'
      },
    };
    request(options, function(err, res, body) {
      if (err) { return console.log(err); }
      var playerInfo = JSON.parse(body);
      responses.push(playerInfo.rank.emea);
      completed_requests++;
      if (completed_requests === players.length) {
        completed_requests = 0;
        eres.send(responses);
        responses = [];
      }
    });
  }
});

app.listen(3000)

我认为我将请求发送到 api 的方式存在问题。我最大的猜测是它与时间和将结果发送回客户端有关。或者使用 siege 是测试此应用程序的不好方法。

【问题讨论】:

  • eres.send(responses); 需要更改。每次在 for 循环中发送响应都是一个问题。我认为您应该继续将 eres 代码移到 for 循环之外,然后您将不再收到此错误。您还需要使这个更加面向承诺,以使其工作而不是回调。我可能会写一个答案来帮助满足您的要求。
  • 另外,我建议您花时间使用环境变量而不是静态字符串,如果您将代码推送到 github 或将其发布到堆栈以寻求帮助,因为您的密钥安全。

标签: express request


【解决方案1】:
const players = [];

app.get(`/`, async (ereq, eres) => {

    const http = (options) => {
        return new Promise((resolve, reject) => {
            request(options, (err, res, body) => {
                if (err) {
                    return reject(err);
                }
                return resolve(JSON.parse(body));
            });
        });
    };



    for(let i = 0; i < players.length; i++) {

        var playerUUID = players[i];
        var options = {
            url: 'https://r6db.com/api/v2/players/' + playerUUID + '?platform=PC',
            headers: {
                'x-app-id': '5e23d930-edd3-4240-b9a9-723c673fb648'
            },
        };

        try {
            let playerInfo = await http(options);
            response.push(playerInfo.rank.emea);
        } catch (e) {
            console.log(e); // I think that you should handle this a better way than just console.logging...
        }
    }

    return eres.json(response);
});

只要确保你使用了 Promise。 Promise 将减慢 for 循环,以便您获得正确的响应,并允许您在返回之前检查所需的任何内容。如果您需要在 for 循环中返回响应,那么我建议您继续尝试并将 break; 退出 for 循环,然后再继续尝试将数据发送到已发送的响应。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-03-03
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多