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

Javascript 在启动时使用同步代码将数据加载到内存中可以吗?,javascript,node.js,asynchronous,express,promise,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.e

在我的
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;
};
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);
            });
        });
    });
};
当我运行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() {
    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;
};
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);
            });
        });
    });
};
假设总页面大小不会超过1MB,我可以无限期地将文本缓存到内存中,而不会因为内存不足而导致节点崩溃

  • 我应该使用异步代码吗

    据我所知,异步版本将使节点更快地开始在本地主机上侦听,但
    /:page
    url仅在文件加载到内存中时才起作用

  • 异步代码的模式是否正确

  • 如果我需要在另一个文件中重用
    页面
    对象,该怎么办?现在它只能在
    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);
        }
    };
    
    var ret=[];
    module.exports=函数(回调){
    var fs=require('fs'),
    目录='/页';
    如果(返回长度<1){
    fs.readdir(dir,函数(err,文件){
    如果(错误)抛出错误;
    forEach(函数(文件){
    fs.readFile(dir+'/'+文件'utf-8',函数(err,text){
    如果(错误)抛出错误;
    var fileName=file.substr(0,file.lastIndexOf('.');
    ret[fileName]={content:text};
    if(i==(files.length-1))回调(ret);
    });
    });
    });    
    }否则{
    回调(ret);
    }
    };
    
  • 如果一起多次调用
    require('./pages')(函数(pages){})
    ,该怎么办?如果条件失败,是否有可能出现?我想不起这件事
  • 我应该使用异步代码吗

    如果你愿意,为什么不呢。但是没有真正的必要,启动时的同步IO是可以的<代码>要求也这样做

    异步代码的模式是否正确

    否。它会为每个目录调用一次
    回调。多次调用app.get('/:page',…)
    不是您想要的

    如果我需要在另一个文件中重用pages对象,该怎么办?目前,它只能在routes.js中访问

    您可以将它从
    routes.js
    传递到其他模块。或者只需重写
    pages.js
    以静态方式存储它,并只执行一次异步操作,这样您就可以多次需要它

    如果一起多次调用
    require('./pages')(函数(pages){})
    ,该怎么办?如果条件失败,是否有可能发生这种情况

    是的,它肯定会失败,因为您只异步填充
    ret

    我想不起这件事

    使用承诺。这个函数可以作为异步的、不可变的值,这正是您需要的。它们将保证回调只调用一次,每个回调都使用相同的
    ret
    值调用,并提供更多有用的功能(比如为您管理并行文件读取)


    您需要从
    pages.js

    导出承诺是的,同步加载(require)是node.js的工作方式,而且人们似乎仍然在使用node.js。。。使用async加载不会带来巨大的回报,因为在满足依赖关系之前,应用程序将无法使用。一旦你走了,同步可以减慢一批请求,但是直到所有的东西被加载为止,没有任何事情发生,所以使用Syc保持快速和简单。也考虑你是从HDD加载的,而不是HTTP。因此,在浏览器中,异步并不像在浏览器中那么重要,在浏览器中,syncajax将冻结选项卡,并且可能需要一段时间……非常感谢您的回答。我完全忽略了异步代码中的回调在循环中这一事实。因此,我可以添加一个if条件,以确保回调仅在循环的最后一次迭代中调用,这也会修复异步代码,对吗?是的,但它非常复杂,并且仍然存在多次调用的问题。只需使用同步代码或承诺。非常感谢,非常感谢您的帮助。我的理解是
    if(i==(files.length-1))回调(ret)
    将完成这项工作(不计算多次调用问题),但
    readFile
    是异步的,因此可以在调用其他回调之前执行最后一次回调。是的,您不能使用闭包中的
    i
    变量,您必须使用每次调用时增加的计数器。但实际上,您不想手动执行此操作,可以使用承诺(
    Promise.all
    )或类似async.js(
    async.parallel
    )的助手库。