Javascript fs.readFile()是否会缓存文件';s服务器中的内容';第一次阅读后的记忆是什么?

Javascript fs.readFile()是否会缓存文件';s服务器中的内容';第一次阅读后的记忆是什么?,javascript,node.js,caching,Javascript,Node.js,Caching,我想知道以下代码在读取一次文件后是否会将其内容缓存在服务器内存中。我问这个问题的原因是因为我不想每次用户请求页面时都要重新读取文件。我更喜欢在第一次读取后将其缓存 fs.exists(fileName, function (exists) { if (!exists) { console.log("== 404 error"); resp.writeHead(404, {'Content-Type': 'text/html'});

我想知道以下代码在读取一次文件后是否会将其内容缓存在服务器内存中。我问这个问题的原因是因为我不想每次用户请求页面时都要重新读取文件。我更喜欢在第一次读取后将其缓存

fs.exists(fileName, function (exists) {
        if (!exists) {
            console.log("== 404 error");
            resp.writeHead(404, {'Content-Type': 'text/html'});
            resp.end(pageError);
            return;
        }

        fs.readFile(fileName, 'utf8', function (err, data) {
            if (err) {
                resp.writeHead(404, {"Content-Type": "text/html"});
                resp.end(pageError);
                return;
            }

            var contentType = getContentType(req.url);
            var mimeType = mimeTypes[contentType];

            resp.writeHead(200, {"Content-Type": mimeType});
            resp.end(data);
        });
    });

注意**我只想知道如何使用内部节点JS模块(无express)

您不应该使用
fs.exists()
作为其弃用版本;如果只想检查是否存在,请使用
fs.stat()
。如果要在检查文件是否存在后打开并读取文件,则只需使用
fs.readFile()
并对不存在的文件相应地处理传递的错误。这在
fs.access()
fs
文档中有所说明,但仍然适用于
fs.stat()
。下面是Node.js文档的摘录

不建议在调用fs.open()、fs.readFile()或fs.writeFile()之前使用fs.access()检查文件的可访问性。这样做会引入竞争条件,因为其他进程可能会在两次调用之间更改文件的状态。相反,用户代码应该直接打开/读取/写入文件,并在文件不可访问时处理引发的错误

fs.readFile()
不会为您进行任何缓存,这是您需要自己创建/管理的内容。下面的示例演示如何使用JS对象作为字典创建文件缓存,以按文件名索引文件内容。重要的是要注意,您不应该在
fileCache
对象中放入Gig数据,相反,这对于许多较小的文件是很好的

fileCache
只需要位于
getFileFromCache()
的范围内,并且位于运行时不会被垃圾收集的位置

const fileCache = {}
const getFileFromCache = (filename, cb) => {
    if (fileCache[filename]) {
        return cb(null, fileCache[filename])
    }

    fs.readFile(filename, 'utf8', (err, data) => {
      if (err) {
        return cb(err)
      }

      fileCache[filename] = data
      return cb(null, data)     
    })
}

如果要跨多个模块访问文件数据,可以将文件数据存储在变量或全局变量中(使用
global.=


当然,正如George Campbell所说,您的程序不会注意到对文件的任何修改,因为它不会重新读取文件。

所以我会这样做:

function sendResponse(data) {
    let contentType = getContentType(req.url);
    let mimeType = mimeTypes[contentType];
    resp.writeHead(200, {"Content-Type": mimeType});
    resp.end(data);
}

if(global.fileData) {
    return sendResponse(global.fileData);
}

fs.readFile(fileName, 'utf8', function (err, data) {
    if (err) {
        resp.writeHead(404, {"Content-Type": "text/html"});
        resp.end(pageError);
        return;
    }

    global.fileData = data;
    sendResponse(global.fileData);
});
第一次global.fileData将为空,因此您将继续执行fs.readfile,将文件内容存储在global.fileData中,然后发送响应。
第二次global.fileData将包含内容,因此您只需发送带有该内容的响应,就不会再次读取该文件。
有关进一步参考,请参阅NodeJS官方文档:

您应该做的另一件事是将fs.exists替换为fs.access或fs.stat(我通常使用fs.access),因为exists方法已被弃用。



快乐编码

在第一次读取后,fs.readFile()会将文件内容缓存在服务器内存中吗

否。
fs.readFile()
本身不进行缓存

但是,底层操作系统将进行文件缓存,只要没有太多其他文件活动导致缓存读取被刷新,那么操作系统可能会在您读取文件的第二次、第三次时从本地内存缓存中获取该文件


如果您想自己确保缓存,那么您应该在首次读取内容后自己存储内容,从那时起,您可以使用以前读取的内容。

只需将数据保存在变量中即可。当用户请求页面时,您不需要这样做,为什么不在服务器启动时这样做呢?这是一种有效的方式吗?一种有效的方式是什么?您可以在启动时读取该文件一次,并在每个页面请求中提供该数据。请记住,如果不再读取该文件,对该文件的更改将不会反映出来。不仅
fs.exists()
已弃用,而且此类代码中也没有理由使用
fs.stat()
。只要执行
fs.readFile()
并在文件不存在时处理错误即可。效率更高,不受比赛条件的限制。@jfriend00当然,如果OP出于某种原因想访问文件统计信息,我会把它放在那里。我将更新我的答案以解决这个问题。@jfriend00更新了我的答案,以更好地解决您提出的比赛条件。