【问题标题】:javascript switch/case breaks before reading filejavascript 在读取文件之前切换/大小写中断
【发布时间】:2014-09-21 12:35:54
【问题描述】:

我正在编写一个带有 socket.io 实现的简单 node.js 服务器。当我去 mylocalip:8005/socket.html 'socket_break' 在控制台中的 'socket_data' 之前打印。所以我在浏览器中看到的是空白页而不是 socket.html 的内容。

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('./socket.html', function(error, data){
            if (error){
                response.writeHead(404);
                response.write("opps this doesn't exist - 404");
                console.log('socket_error');
            }
            else{
                response.writeHead(200, {"Content-Type": "text/html"});
                response.write(data, "utf8");
                console.log('socket_data');

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

server.listen(8005);

如何在读取文件之前防止开关/大小写中断并使浏览器显示我的 socket.html 文件的内容?

【问题讨论】:

  • 错误不应该在那个级别处理,它应该发生在你之前,甚至在你到达路线之前。那时你可以这样做:var fileStream = fs.createReadStream('socket.html');fileStream.pipe(response);
  • 问题是你甚至在 readFile 完成之前就结束了响应。最简单的解决方案是将response.end 移动到您的案例语句中,并在/socket.html 的情况下移动到readFile 中。这意味着大量的代码重复。如果您不希望这样,您可能想要更改@Robert 在他的回答中提到的架构。

标签: javascript html node.js socket.io


【解决方案1】:

最简单的方法是只使用return;,但您必须记住在回调中使用response.end();

另一种解决方案可能是在启动服务器之前将文件读入内存,然后执行response.writeHead(...); response.end(socketFileBuf); 之类的操作。显然,如果您有大量文件、非常大的文件或想要发送任意文件,您可能不想这样做。但是对于像您在这里可能拥有的简单 html 文件,它应该可以很好地工作并且会减少响应时间。

【讨论】:

    【解决方案2】:

    fs.readFile 是异步的,因此在读取文件时不会阻塞。

    改用 fs.readFileSync。

    【讨论】:

      【解决方案3】:

      这取决于你要完成什么,fs.readFile 是异步的,所以这种情况下如果只是在控制台上打印,请将打印放在回调文件中。

      如果也是为了进一步执行,我建议你使用fs.readFileSync,如果你是 Node.js 的新手,同步工作也会容易得多。

      【讨论】:

        【解决方案4】:

        我会远离在 node.js 中做同步的东西,因为当你阻塞时,你会让每个发出请求的人都搁置。相反,将您的路线从错误处理中抽象出来。显然,关于你想如何做到这一点存在一些架构上的争论,但我就是这样做的:)

        var http = require("http");
        var url = require('url');
        var fs = require('fs');
        
        // Perhaps include this via a require('httpExceptionHandler')
        function httpExceptionHandler(req, res) {
            return {
                404: function() {
                    res.statusCode = 404;
                    res.end("opps this doesn't exist - 404");
                },
        
                500: function(error) {
                    res.statusCode = 500;
                    res.end("internal server error");
                }
            }
        }
        
        
        // Perhaps include this via a require('routes')
        var routes = {
            '/': function(server) {
                var res = server.response;
                res.setHeader('Content-Type', 'text/plain');
                res.end('hello world');
            },
        
            '/socket.html': function(server) {
                var fileStream = fs.createReadStream('socket.html');
                fileStream.on('error', server.httpExceptionHandler['500']);
                fileStream.pipe(server.response);
            }
        };
        
        
        var server = http.createServer(function(request, response){
            var path = url.parse(request.url).pathname;
            var routeFn = routes[path];
        
            var server = {
                httpExceptionHandler: httpExceptionHandler(request, response),
                request: request,
                response: response
            };
        
            if (routeFn) {
                // Set some default headers
                response.statusCode = 200;
                response.setHeader('Content-Type', 'text/html');
        
                // A better design might be to return an action like
                // Redirect, Exception, etc... not sure
                routeFn(server);
            } else {
                server.httpExceptionHandler['404']();
            }
        });
        
        server.listen(8005);
        

        在我们完全完成之前,我们不会结束response,这使得上述代码能够正常运行。

        【讨论】:

        • 这种方式的问题在于,如果读取文件时出现(立即)错误(例如文件不存在或权限问题),则无法返回更合适的状态码给用户,因为res.end();(由pipe()调用)将发送状态码200。
        • 啊,我明白了……怎么样?
        猜你喜欢
        • 2022-01-02
        • 1970-01-01
        • 1970-01-01
        • 2023-04-02
        • 2020-04-26
        • 1970-01-01
        • 2012-06-01
        • 2015-04-24
        • 1970-01-01
        相关资源
        最近更新 更多