如何将使用 fs.readFileSync() 的 Node.js 代码重构为使用 fs.readFile()?

Posted

技术标签:

【中文标题】如何将使用 fs.readFileSync() 的 Node.js 代码重构为使用 fs.readFile()?【英文标题】:How to refactor Node.js code that uses fs.readFileSync() into using fs.readFile()? 【发布时间】:2014-05-16 18:56:15 【问题描述】:

我试图了解 Node.js 中的同步与异步,尤其是在读取 html 文件时。

在请求处理程序中,我正在使用的同步版本如下:

    var fs = require("fs");
    var filename = "./index.html";
    var buf = fs.readFileSync(filename, "utf8");
    
    function start(resp) 
        resp.writeHead(200,  "Content-type": "text/html" );
        resp.write(buf);
        resp.end();
    
    
    exports.start = start; 
    使用readFile() 的版本是什么? 我知道readFile是异步的,所以理论上我应该等待整个文件被读取后再渲染,所以我应该引入addListener吗?我可能会混淆不同的东西。

编辑:我曾尝试像这样重构代码:

    var fs = require("fs");
    var filename = "./index.html";
    function start (resp) 
        resp.writeHead(200,  "Content-Type": "text/html" );
        fs.readFile(filename, "utf8", function (err, data) 
            if (err) throw err;
            resp.write(data);
        );
        resp.end();
    

我得到一个空白页。我猜是因为它应该等待读取所有数据,在resp.write(data)之前,我该如何发出这个信号?

【问题讨论】:

您是否在问,如果您要使用 readFile(),等效代码是什么?您将如何处理异步发送内容? @AnthonyForloney 是的,这就是我要问的,使用 fs.readFile() 的等效代码是什么? 在您的回调中移动resp.end()。这就是你得到一个空白页的原因。 @AnthonyForloney 是的,我在 lombausch 的回答中看到了这一点,你知道为什么我需要将 resp.end() 放在回调中吗?谢谢 当你在上面的代码中使用异步方法时,比如readFile,你告诉程序“读取文件的内容,当你完成时(关键字,'when')读取内容,将它们用作响应主体”。如果在回调中不提供resp.end() 调用(如上所示),程序会调用readFile,然后在你的回调有时间执行resp.write 之前立即调用resp.end()。这有意义吗? 【参考方案1】:
var fs = require("fs");
var filename = "./index.html";

function start(resp) 
    resp.writeHead(200, 
        "Content-Type": "text/html"
    );
    fs.readFile(filename, "utf8", function(err, data) 
        if (err) throw err;
        resp.write(data);
        resp.end();
    );

【讨论】:

谢谢,它确实有效。后续问题,您可能已经看到我的编辑,在我的暂定答案中,我没有在回调中包含 resp.end(),这不起作用,您知道为什么它必须在回调中吗? Rgds 如果您不在回调中提供它,您的resp.end() 将立即被调用,因为它不等待回调的响应。【参考方案2】:

这个变种更好,因为你不知道文件是否存在。当您确定可以读取文件内容时,您应该发送正确的标题。此外,如果您有没有以 '.end()' 结尾的代码分支,浏览器将等到它得到它们。也就是说,您的浏览器会等待很长时间。

var fs = require("fs");
var filename = "./index.html";

function start(resp) 

    fs.readFile(filename, "utf8", function(err, data) 
        if (err) 
            // may be filename does not exists?
            resp.writeHead(404, 
                'Content-Type' : 'text/html'
            );
            // log this error into browser
            resp.write(err.toString());
            resp.end();
         else 

            resp.writeHead(200, 
                "Content-Type": "text/html"
            );      
            resp.write(data.toString());
            resp.end();
        
    );

【讨论】:

以上是关于如何将使用 fs.readFileSync() 的 Node.js 代码重构为使用 fs.readFile()?的主要内容,如果未能解决你的问题,请参考以下文章

fs.readFileSync无法读取nodejs中的文件传递路径变量

使用 lambda 部署时 fs.readFileSync 找不到文件

fs.readFileSync 总是返回空字符串

fs.readFileSync 不是 Meteor 的函数,React

JavaScript - 使用 require 读取 JSON 文件的结果与 fs.readFileSync 不同

如何从节点中的ReadStream同步读取