在我的 routes.js
文件中,我有这个:
var pages = require('./pages')();
...
app.get('/:page', function(req, res, next) {
var p = req.params.page;
if (p in pages) {
res.render('page', pages[p]);
} else {
next();
}
});
pages.js
:
module.exports = function() {
var fs = require('fs'),
ret = [],
dir = './pages',
files = fs.readdirSync(dir);
files.forEach(function(file) {
var text = fs.readFileSync(dir + '/' + file, 'utf-8'),
fileName = file.substr(0, file.lastIndexOf('.'));
ret[fileName] = {content: text};
});
return ret;
};
当我运行 Node 时,此代码仅运行一个。这就是我如何使其异步:
require('./pages')(function(pages) {
app.get('/:page', function(req, res, next) {
var p = req.params.page;
if (p in pages) {
res.render('page', pages[p]);
} else {
next();
}
});
});
pages.js
:
module.exports = function(callback) {
var fs = require('fs'),
ret = [],
dir = './pages';
fs.readdir(dir, function(err, files) {
if (err) throw err;
files.forEach(function(file, i) {
fs.readFile(dir + '/' + file, 'utf-8', function(err, text) {
if (err) throw err;
var fileName = file.substr(0, file.lastIndexOf('.'));
ret[fileName] = {content: text};
if ( i === (files.length - 1) ) callback(ret);
});
});
});
};
假设总页面大小不超过 1 MB,我可以无限期地将文本缓存到内存中,而不会因内存不足而导致 Node 崩溃。
我应该使用异步代码吗?
根据我所了解到的,异步版本将使 Node 更快地开始在本地主机上监听,但是
/:page
URL 仅在文件加载到内存中时才起作用。异步代码的模式是否正确?
如果我需要在另一个文件中重用
pages
对象怎么办?目前只能在routes.js
中访问它。
我可以重写 pages.js
使其仅执行一次吗:
var ret = [];
module.exports = function(callback) {
var fs = require('fs'),
dir = './pages';
if (ret.length < 1) {
fs.readdir(dir, function(err, files) {
if (err) throw err;
files.forEach(function(file) {
fs.readFile(dir + '/' + file, 'utf-8', function(err, text) {
if (err) throw err;
var fileName = file.substr(0, file.lastIndexOf('.'));
ret[fileName] = {content: text};
if ( i === (files.length - 1) ) callback(ret);
});
});
});
} else {
callback(ret);
}
};
- 如果
require('./pages')(function(pages) {})
被多次调用会怎样?if
条件是否有可能失败?我无法全神贯注于此。
最佳答案
Should I be using the async code?
如果你愿意,为什么不呢?但其实没有必要,启动时同步 IO 就可以了。 require
也能做到这一点。
Is the async code in the right pattern?
没有。它确实为每个目录调用一次回调。多次调用 app.get('/:page', …)
并不是您想要的。
What if I need to reuse the pages object in another file? Right now it is only accessible in routes.js.
您可以将其从routes.js
传递到其他模块。或者只需重写 pages.js
以静态存储它并仅执行一次异步操作,以便您可以多次调用它。
What if
require('./pages')(function(pages) {})
is called multiple times together? Is there a chance of the if condition failing?
是的,它肯定会失败,因为您只是异步填充 ret
。
I can't wrap my mind around this.
使用 promise 。作为异步的、不可变的值,这正是您所需要的。它们将保证回调仅被调用一次,每个回调都使用相同的 ret 值调用,并提供许多更有用的东西(例如为您管理并行文件读取)。
您需要从 pages.js
导出 promise 。
关于javascript - 启动时使用同步代码将数据加载到内存中可以吗?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/30006901/