我得到一个"错误:写完后#34;在NodeJS / javascript中,是什么导致这个?

时间:2017-11-28 23:20:56

标签: javascript json node.js httpserver

因此,这是运行我的http服务器的代码,它将GET请求中的密钥与名为"用户"的JSON文件中的密钥进行比较,向下显示一点。如果我使用此文件中列出的前两个用户之一的密钥,它工作正常,并响应就像我想要的那样。但是,当我使用第三个用户的密钥时,它会响应403错误(它会运行the response.writeHead(403);行。这可能是什么原因造成的?(请参阅以下错误代码:https://imgur.com/a/jC7zn

var httpserver = http.createServer(function(request, response) {
  try {
    var key = '';
    if (request.url.indexOf('k=') != -1) {
        key = request.url.substring(request.url.indexOf('k=') + 2);
    }
    for (i = 0; i < Object.keys(users).length; i++) {
      if (users[Object.keys(users)[i]].apikey == key) {
        response.writeHead(200, {
          'Content-Type': 'application/json'
        });
        response.write(JSON.stringify(users, null, '\t'));
        response.end();
      } else {
        response.writeHead(403);
        response.end();
      }
    }
  } catch (err) {
    console.log(err);
  }
});

&#34;用户&#34; JSON文件(id&#39; s,名称和APIkeys由于某些原因而被混淆):

{   "user1": {
        "auth": "3",
        "name": "Name1",
        "apikey": "key1"   },
    "user2": {
        "auth": "3",
        "name": "Name2",
        "apikey": "key2"   },
    "user3": {
        "auth": "3",
        "name": "Name3",
        "apikey": "key3"   }
}

这是我得到的错误:

Error: write after end
    at write_ (_http_outgoing.js:625:15)
    at ServerResponse.write (_http_outgoing.js:620:10)
    at Server.<anonymous> (pathtoserver/server.js:42:16)
    at emitTwo (events.js:126:13)
    at Server.emit (events.js:214:7)
    at parserOnIncoming (_http_server.js:602:12)
    at HTTPParser.parserOnHeadersComplete (_http_common.js:117:23)

注意,第42行char 16(在服务器端。(pathtoserver / server.js:42:16))是指 response.write(JSON.stringify(users, null, '\t'));在顶部的代码中。

我觉得这与循环在找到第三个用户之前花了太长时间,以及之前关闭的连接有关。这可能是什么?

我希望我提供了足够的信息,如果没有,请务必提出我可以添加的其他内容,这将有助于您的帮助!

P.S。请注意,英语不是我的母语,而且我还在高中,这意味着本文中可能会有一些错误。

1 个答案:

答案 0 :(得分:0)

即使在响应

之后,您仍在运行循环

您需要在撰写回复后退出循环。否则它将继续运行并将获得更多结果,并将尝试发送更多响应。

修复非常简单,只需在response.end();之后添加一个返回true,这将确保循环退出。

你正在以错误的方式进行循环

你可能想确定url是否有密钥,然后返回结果,否则抛出403.

但你在那个循环中使用了else,这意味着如果它在第一次运行时找不到密钥,它就会抛出403并继续循环。

这是一个有效的代码。

const http = require('http')
const port = process.env.PORT;

const requestHandler = (request, response) => {
  try {
    var key = '';

    if (request.url.indexOf('k=') !== -1) {
        key = request.url.substring(request.url.indexOf('k=') + 2);
    }

    // Make sure there is a key and it's not empty
    // if it's not empty, then run the loop.
    if(key.length){
    for (let i = 0; i < Object.keys(users).length; i++) {
      if (users[Object.keys(users)[i]].apikey == key) {
        response.writeHead(200, {
          'Content-Type': 'application/json'
        });
        response.write(JSON.stringify(users, null, '\t'));
        response.end();
        return; // if a result is found, then exit the loop
      } 
    }  
    }

    // if it's empty, then throw 403
    else {
        response.writeHead("403");
        response.end();
      }
  } catch (err) {
    console.log(err);
  }
}

const server = http.createServer(requestHandler)
server.listen(port, (err) => {
  if (err) {
    return console.log('something bad happened', err)
  }

  console.log(`server is listening on ${port}`)
})

我将requestHandler移动到一个单独的位置以保持它有点干净。

希望这有帮助。