javascript - 启动时使用同步代码将数据加载到内存中可以吗?

标签 javascript node.js asynchronous express promise

在我的 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 崩溃。

  1. 我应该使用异步代码吗?

    根据我所了解到的,异步版本将使 Node 更快地开始在本地主机上监听,但是 /:page URL 仅在文件加载到内存中时才起作用。

  2. 异步代码的模式是否正确?

  3. 如果我需要在另一个文件中重用 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/

    相关文章:

    javascript - 原型(prototype)方法可以访问构造函数的上下文(闭包)

    javascript - jQuery 查找元素 :contains, 然后获取类

    javascript - 如何在MySql中保存和读取特殊字符? (Mysqljs 和 Node )

    node.js - 仅显示用于调试 Node.js 的旧版本和预览选项

    c# - ajax表单多个请求怎么办

    javascript - 什么时候使用 _.bind 与 _.bindAll?

    javascript - 从每个 javascript 数组 concat 中获取 1 个元素,然后循环到一个数组中

    javascript - 在模块中使用 express.js 创建 Socket.IO 服务器并从其他模块访问它

    c++有没有一种方法可以在不中断他的工作的情况下有效地与线程通信

    javascript - AMP 需要异步 js;有没有办法进行本地回退?