gpt4 book ai didi

node.js - HTTP状态码200,但页面无法加载Node.js Socket.io —带有Socket.io,Daniel Nill,fs.readFile(),socket.html的Node.js教程

转载 作者:太空宇宙 更新时间:2023-11-03 22:17:37 24 4
gpt4 key购买 nike

了解node.js和socket.io并通过this tutorial by Daniel Nill进行工作。服务器启动没有问题。但是,当我导航到localhost:8001 / socket.html时,会收到默认错误消息。因此,我将switch语句更改为“ /socket.html”,而不是“ socket.html”。现在,该页面加载状态代码200,但没有任何内容呈现到屏幕上。屏幕上应该显示“这是我们的socket.html文件”。是什么赋予了?

服务器端js代码是

var http = require("http");
var url = require('url');
var fs = require('fs');

var server = http.createServer(function(request, response){
console.log('Connection');
var path = url.parse(request.url).pathname;

switch(path){
case '/':
response.writeHead(200, {'Content-Type': 'text/html'});
response.write('hello world');
break;
case 'socket.html':
fs.readFile(__dirname + path, function(error, data){
if (error){
response.writeHead(404);
response.write("opps this doesn't exist - 404");
}
else{
response.writeHead(200, {"Content-Type": "text/html"});
response.write(data, "utf8");
}
});
break;
default:
response.writeHead(404);
response.write("opps this doesn't exist - 404");
break;
}
response.end();
});

server.listen(8001);


与server.js位于同一目录中的Socket.html包含此内容

<html>
<head></head>
<body>This is our socket.html file</body>
</html>


好的,我放弃了这个,转而使用 this example,它可以直接使用!

最佳答案

初学者在这里。据我所知,丹尼尔·尼尔(Daniel Nill)为教程编写了很多代码,但从未成功。结果,他使初学者更加困惑-他声称这是他想缓解的事情。


  因此,我将switch语句更改为“ /socket.html”,而不是“ socket.html”。


那是一个明显的错误-不错的收获。


  现在,该页面的状态代码为200,但没有任何内容呈现给
  屏幕。屏幕上应该显示“这是我们的socket.html文件”。什么
  给?


或者,就像我看到的那样,如果socket.html文件不存在,则不会得到404错误,而是得到状态码200(确定)和一个空网页。

本教程中的代码不起作用的原因是因为Daniel Nill认为自己会很聪明并且不会在每个response.end()之后写response.write()。他以为自己可以在所有代码的末尾写一个response.end()

在我看来,Daniel Nill误解了nodejs的工作方式。也就是说,nodejs不会执行一个函数,然后等待作为参数传递的处理程序函数在执行下一行代码之前完成执行。如果nodejs确实做到了,那么我们就不需要将代码放入处理函数中。相反,nodejs将处理程序功能添加到将来要在某个时间执行的处理程序功能列表。

查看这段代码中的fs.readFile()函数:

switch(path){
case '/':
response.writeHead(200, {'Content-Type': 'text/html'});
response.write('hello world');
break;
case 'socket.html':
fs.readFile(__dirname + path, function(error, data){
if (error){
response.writeHead(404);
response.write("opps this doesn't exist - 404");
}
else{
response.writeHead(200, {"Content-Type": "text/html"});
response.write(data, "utf8");
}
});
break;
default:
response.writeHead(404);
response.write("opps this doesn't exist - 404");
break;
}
response.end();


fs.readFile()的处理函数是以下部分:

        function(error, data){
if (error){
response.writeHead(404);
response.write("opps this doesn't exist - 404");
}
else{
response.writeHead(200, {"Content-Type": "text/html"});
response.write(data, "utf8");
}
});


当浏览器请求 /socket.html时,nodejs执行 fs.readFile(),然后nodejs将其处理函数添加到等待执行的处理函数列表中,然后nodejs继续运行。将执行的下一行代码是 response.end()此处:

    default:
response.writeHead(404);
response.write("opps this doesn't exist - 404");
break;
}

response.end(); //<====HERE ******


对我来说很明显,在fs.readFile()的处理函数执行之前,nodejs会执行该 response.end()

根据 response.end()的文档:


  response.end([数据],[编码])
  该方法向服务器发出信号
  所有响应头和主体都已发送;该服务器
  应该考虑此消息是否完整。方法response.end()
  必须在每个响应上调用。


我对其进行了测试,如果您不执行任何response.write()而仅调用 response.end(),则nodejs将创建一个状态码为200的空响应,例如:

  switch(path) {
case '/':
//resp.writeHead(200, {'Content-Type': 'text/html'} );
//resp.write('<h3>Root page</h3>');
resp.end();
break;


我认为,要从Daniel Nill的错误中吸取的教训是,在为nodejs提供处理程序函数之后,您将无法控制处理程序函数执行后在哪里执行。实际上,在处理程序函数结束之后编写的代码可以在处理程序函数执行之前执行。结果,处理程序函数需要自己完成所有需要做的事情。

以下是使本教程中的示例正常工作所必需的修改:

var http = require('http');
var url = require('url');
var fs = require('fs');

var server = http.createServer(function(requ, resp) {
//requ.url => everything after the host--including the query string
//url.parse(requ.url).pathname => the portion of requ.url before the query string
var path = url.parse(requ.url).pathname;

//The following is so that the automatic request that all browsers make
//for favicon.ico (which for some reason is not logged by any developer
//tools) will not display a 'connection' message:

if (path == '/favicon.ico') {
resp.writeHead(200, {'Content-Type': 'image/x-icon'} );
resp.end();
return; //Terminate execution of this function, skipping the code below.
}

//Router:
switch(path) {
case '/':
resp.writeHead(200, {'Content-Type': 'text/html'} );
resp.write('<h3>Root page</h3>');
resp.end();
break;
case '/socket.html':
fs.readFile(__dirname + path, function(error, data) {
if (error) {
console.log('file error');
resp.writeHead(404);
resp.write("oops, this doesn't exist - 404");
resp.end();
}
else {
console.log('no file error');
resp.writeHead(200, {'Content-Type': 'text/html'} );
resp.write(data, 'utf8');
resp.end();
}
});
break;
default:
resp.writeHead(404);
resp.write("oops, this doesn't exist - 404");
resp.end();
break;
}

console.log('Connection');
});

port = 8888;
console.log('Server listening on port ' + port);
server.listen(port);


为了最大程度地减少必须调用 response.end()的次数,可以执行以下操作:

var http = require('http');
var url = require('url');
var fs = require('fs');

var server = http.createServer(function(requ, resp) {
//console.log('request url: ' + requ.url);

//requ.url => everything after the host--including the query string
//url.parse(requ.url).pathname => the portion of requ.url before the query string
var path = url.parse(requ.url).pathname;

//The following is so that the automatic request that all browsers make
//for favicon.ico (which for some reason is not logged by any developer
//tools) will not cause a 'connection' message:

if (path == '/favicon.ico') {
resp.writeHead(200, {'Content-Type': 'image/x-icon'} );
resp.end();
return;
}

//Router:
switch(path) {
case '/':
resp.writeHead(200, {'Content-Type': 'text/html'} );
resp.write('<h3>Root page</h3>');
resp.end();
break;
case '/socket.html':
fs.readFile(__dirname + path, function(error, data) {
if (error) {
console.log('file error');
resp.writeHead(404);
resp.write("oops, this doesn't exist - 404");
//resp.end();
}
else {
console.log('no file error');
resp.writeHead(200, {'Content-Type': 'text/html'} );
resp.write(data, 'utf8');
//resp.end();
}
resp.end();
});
break;
default:
resp.writeHead(404);
resp.write("oops, this doesn't exist - 404");
resp.end();
break;
}
//resp.end();
console.log('Connection');
});



port = 8888;
console.log('Server listening on port ' + port);
server.listen(port);


但是您不能完全从处理函数中重构 response.end(),就像Daniel Nill所做的那样。并且您不能在switch语句后放置 response.end(),因为 response.end()将在传递给fs.readFile()的处理程序函数执行之前执行,这将导致状态值为200的空请求发送到浏览器。

此外,对于单个请求,我收到了两个“连接”消息。当我输入以下网址时,我的开发人员工具仅显示浏览器发送的一个请求:

http://localhost:8888/


...但是所有浏览器都会发送一个附加请求,以检索 /favicon.ico。您可以通过编写类似以下内容来证明是这种情况:

var server = http.createServer(function(requ, resp) {
console.log('request url: ' + requ.url);


为了解决双重请求问题,我添加了if语句:

if (path == '/favicon.ico') {...


...描述如下:

http://tinyurl.com/odhs5le

=====

在本教程的下一部分中,为了在使用socket.io时看到命令行输出,必须使用以下命令来启动服务器:

 $ DEBUG=socket.io:* node server.js


请参见nodejs文档“从0.9升级”的 Log differences部分:

http://socket.io/docs/migrating-from-0-9/

=====

为了使socket.io代码的一部分正常工作,我在 server.js中添加了以下内容:

var http = require('http');
var url = require('url');
var fs = require('fs');
var io = require('socket.io'); //New code

var server = http.createServer(function(requ, resp) {
...
...
...
});

port = 8888;
console.log('Server listening on port ' + port);
server.listen(port);

//New code:
var websockets_listener = io.listen(server);
websockets_listener.sockets.on('connection', function(socket){
socket.emit('server message', {"message": "hello world"});
});


然后在 socket.html中,我有这个:

<html>
<head>
<script src="/socket.io/socket.io.js"></script>
</head>
<body>

<div>This is our socket.html file</div>
<div id="message"></div>

<script>
var socket = io.connect();
//More recent versions of socket.io allow you to simply write:
//var socket = io();
//which both creates the socket and by default connects to
//the same host that served this page.
//See: http://socket.io/get-started/chat/, section Integrating Socket.IO

socket.on('server message', function(data) {
document.getElementById('message').innerHTML = data.message;
});
</script>
</body>
</html>


您可以这样做:

     socket.on('server message', function(data) {
console.log(data.message);
});


...但是您必须记住,在nodejs中,console.log()输出进入服务器窗口,但是当javascript在网页上执行时,例如socket.html,console.log()输出进入网络浏览器的控制台(显示Web浏览器的开发工具以查看控制台)-因此,请勿在服务器窗口中查找输出。

===

在本教程的下一部分中,要仅流化时间,消除日期,毫秒,utc偏移量等,这只会使所有内容混乱,可以在 server.js中执行此操作:

var websockets_listener = io.listen(server);
websockets_listener.sockets.on('connection', function(socket){

setInterval(function() {
var now = new Date();
socket.emit('time', {local_time: now.toLocaleTimeString()})
}, 1000);

});


socket.html

<html>
<head>
<script src="/socket.io/socket.io.js"></script>
</head>
<body>
<div>This is our socket.html file</div>
<div id="message"></div>

<script>
var socket = io.connect();

socket.on('time', function(data) {
document.getElementById('message').innerHTML = data.local_time;
});
</script>
</body>
</html>


===

在本教程的下一部分中,可以将数据从客户端流传输到服务器,您可以执行此操作(请注意对jquery的更正,但修正不多):

socket.html

<html>
<head>
<script src="/socket.io/socket.io.js"></script>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.js"></script>
</head>
<body>
<div>This is our socket.html file</div>
<div id="time"></div>
<textarea id="text"></textarea>


<script>
var socket = io.connect();

socket.on('time', function(data) {
$('#time').html(data.local_time);
});

//Because the html above has already been parsed by the time this
//js executes, there is no need for document.ready():

$('#text').on('keypress', function(event) {
var keycode = event.which;
socket.emit('client data', {letter: String.fromCharCode(keycode)} );
});
</script>
</body>
</html>


server.js

var http = require('http');
var url = require('url');
var fs = require('fs');
var io = require('socket.io');

var server = http.createServer(function(requ, resp) {
...
...
...
});

port = 8888;
console.log('Server listening on port ' + port);
server.listen(port);

var websockets_listener = io.listen(server);

//websockets_listener.set('log level', 1);
//Rather than writing the previous line(which doesn't work anymore)
//just stop the server and restart it using this command:
//$ node server.js
//...instead of:
//$ DEBUG=socket.io:* node server.js

websockets_listener.sockets.on('connection', function(socket){

setInterval(function() {
var now = new Date();
socket.emit('time', {local_time: now.toLocaleTimeString()})
}, 1000);

socket.on('client data', function(data) {
process.stdout.write(data.letter);
});

});

关于node.js - HTTP状态码200,但页面无法加载Node.js Socket.io —带有Socket.io,Daniel Nill,fs.readFile(),socket.html的Node.js教程,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/20363617/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com