竞争条件与文件加载

如果我通过命令行使用节点并需要模块,请使用load函数,然后使用get函数从configuration文件返回期望的string。

 ➜ cz node > var config = require('./index.js'); undefined > config.load('/Users/xo/code/cz/config.json'); undefined > config.get() { username: 'xo' } > config.get('username') 'xo' 

如果我通过文件尝试相同的事情,我得到undefined返回而不是{ username: xo }

 ➜ cz node test.js undefined 

这是test.js文件。

 var config = require('./index.js'); config.load('./config.json'); console.log(config.get('username')); 

这是我的模块。

 'use strict'; const fs = require('fs'); let config = {}; module.exports = { load: function(path) { fs.readFile(path, function(err, data) { if (err) { throw err; } data = JSON.parse(data); for(var prop in data){ if (data.hasOwnProperty(prop)) { config[prop] = data[prop]; } } }); }, get: function(prop){ if(prop){ return config[prop]; } else { return config; } }, set: function(prop, value) { config[prop] = value; return config[prop]; } }; 

这是config.json文件。

 { "username": "xo" } 

你的load函数是asynchronous的。 这意味着它开始操作并立即返回,然后实际操作结束一段时间。 您需要将接口更改为load函数,以便调用者可以知道何时完成以及何时可以安全地执行其他操作。

这里有很多可能的devise。 一种方式是这样的:

 'use strict'; const fs = require('fs'); let config = {}; module.exports = { load: function(path, callback) { fs.readFile(path, function(err, data) { if (err) { return callback(err);} data = JSON.parse(data); for(var prop in data){ if (data.hasOwnProperty(prop)) { config[prop] = data[prop]; } } // communicate that all data is now loaded callback(null); }); }, get: function(prop){ if(prop){ return config[prop]; } else { return config; } }, set: function(prop, value) { config[prop] = value; return config[prop]; } }; 

然后,你的调用者可以知道加载操作何时完成:

 var config = require('./index.js'); config.load('./config.json', function(err) { // in here, we know that the config data is done loading if (err) { console.log(err); } else { console.log(config.get('username')); } }); 

另外,请认识到,你在asynchronouscallback中做一个throw err是不行的。 这个exception只是回到了fs.readFile()函数的内部,而且你的代码都没有看到这个exception。 这就是为什么我使用callback和node.jscallback调用约定来传递错误。

另外,您可能想要了解require()函数(如果给定的文件名以.json结尾)将自动为您parsingJSON,并且会同步加载它(这是在加载configuration信息时用于启动的) 。

所以,你也可以这样做:

 let config = require('/Users/xo/code/cz/config.json'); 

require()会同步加载数据(类似于fs.readFileSync() ),所以你不必使用callbackscheme。


如果你的代码是这样的,configuration可以在启动时同步加载,那么你可以这样做:

 'use strict'; const fs = require('fs'); module.exports = function(path) { let config = require(path); return { get: function(prop) { if (prop) { return config[prop]; } else { return config; } }, set: function(prop, value) { config[prop] = value; return config[prop]; } } } 

然后,它的使用将如下所示:

 var config = require('./index.js')('./config.json'); console.log(config.get('username')); 

你也可以像这样简化你的load()方法:

 'use strict'; const fs = require('fs'); let config = {}; module.exports = { load: function(path) { Object.assign(config, require(path)); }, get: function(prop){ if(prop){ return config[prop]; } else { return config; } }, set: function(prop, value) { config[prop] = value; return config[prop]; } };