简体   繁体   English

使用 require vs fs.readFile 读取 json 文件内容

[英]Read json file content with require vs fs.readFile

Suppose that for every response from an API, i need to map the value from the response to an existing json file in my web application and display the value from the json.假设对于来自 API 的每个响应,我需要将来自响应的值映射到我的 Web 应用程序中现有的 json 文件并显示来自 json 的值。 What are the better approach in this case to read the json file?在这种情况下读取 json 文件的更好方法是什么? require or fs.readfile.要求或 fs.readfile。 Note that there might be thousands of request comes in at a same time.请注意,可能有数千个请求同时传入。

Note that I do not expect there is any changes to the file during runtime.请注意,我不希望在运行时对文件有任何更改。

request(options, function(error, response, body) {
   // compare response identifier value with json file in node
   // if identifier value exist in the json file
   // return the corresponding value in json file instead
});

I suppose you'll JSON.parse the json file for the comparison, in that case, require is better because it'll parse the file right away and it's sync:我想你会 JSON.parse json 文件进行比较,在这种情况下, require更好,因为它会立即解析文件并且它是同步的:

var obj = require('./myjson'); // no need to add the .json extension

If you have thousands of request using that file, require it once outside your request handler and that's it:如果您有数千个使用该文件的请求,请在您的请求处理程序之外要求它一次,就是这样:

var myObj = require('./myjson');
request(options, function(error, response, body) {
   // myObj is accessible here and is a nice JavaScript object
   var value = myObj.someValue;

   // compare response identifier value with json file in node
   // if identifier value exist in the json file
   // return the corresponding value in json file instead
});

There are two versions for fs.readFile , and they are fs.readFile有两个版本,它们是

Asynchronous version异步版本

require('fs').readFile('path/test.json', 'utf8', function (err, data) {
    if (err) 
       // error handling

    var obj = JSON.parse(data);
});

Synchronous version同步版本

var json = JSON.parse(require('fs').readFileSync('path/test.json', 'utf8'));

To use require to parse json file as below使用require解析json文件如下

var json = require('path/test.json');

But, note that但是,请注意

  • require is synchronous and only reads the file once, following calls return the result from cache require是同步的并且只读取文件一次,随后的调用从缓存中返回结果

  • If your file does not have a .json extension, require will not treat the contents of the file as JSON .如果您的文件没有.json扩展名,则 require 不会将文件内容视为JSON

Since no one ever cared to write a benchmark, and I had a feeling that require works faster, I made one myself.因为从来没有人关心写一个基准,而且我觉得需要更快的工作,所以我自己做了一个。

I compared fs.readFile (promisified version) vs require (without cache) vs fs.readFileSync.我比较了 fs.readFile(promisified 版本)与 require(无缓存)与 fs.readFileSync。

You can see benchmark here and results here .您可以在此处查看基准测试并在此处查看结果。

For 1000 iterations, it looks like this:对于 1000 次迭代,它看起来像这样:

require: 835.308ms
readFileSync: 666.151ms
readFileAsync: 1178.361ms

So what should you use?那么你应该使用什么? The answer is not so simple.答案并非如此简单。

  1. Use require when you need to cache object forever.当您需要永久缓存对象时使用 require。 And better use Object.freeze to avoid mutating it in application.最好使用 Object.freeze 来避免在应用程序中改变它。
  2. Use readFileSync in unit tests or on blocking application startup - it is fastest.在单元测试或阻止应用程序启动时使用 readFileSync - 它是最快的。
  3. Use readFile or promisified version when application is running and you don't wanna block event loop.当应用程序正在运行并且您不想阻止事件循环时,请使用 readFile 或 promisified 版本。

Use node-fixtures if dealing with JSON fixtures in your tests.如果在测试中处理 JSON 固定装置,请使用节点固定装置。

The project will look for a directory named fixtures which must be child of your test directory in order to load all the fixtures (*.js or *.json files):该项目将查找名为 fixtures 的目录,该目录必须是您的测试目录的子目录,以便加载所有的 fixtures(*.js 或 *.json 文件):

// test/fixtures/users.json
{
  "dearwish": {
    "name": "David",
    "gender": "male"
  },
  "innaro": {
    "name": "Inna",
    "gender": "female"
  }
}
// test/users.test.js
var fx = require('node-fixtures');
fx.users.dearwish.name; // => "David" 
{
  "country": [    
    "INDIA",
    "USA"
  ],
  "codes": [   
    "IN",
    "US"
  ]
}

// countryInfo.json

const { country, code } = require('./countryInfo.json');

console.log(country[0]); // "INDIA"
console.log(code[0]); // "IN"

I only want to point out that it seems require keeps the file in memory even when the variables should be deleted.我只想指出,即使应该删除变量,似乎也require将文件保存在内存中。 I had following case:我有以下案例:

for (const file of fs.readdirSync('dir/contains/jsons')) {
  // this variable should be deleted after each loop
  // but actually not, perhaps because of "require"
  // it leads to "heap out of memory" error
  const json = require('dir/contains/jsons/' + file);
}

for (const file of fs.readdirSync('dir/contains/jsons')) {
  // this one with "readFileSync" works well
  const json = JSON.parse(fs.readFileSync('dir/contains/jsons/' + file));
}

The first loop with require can't read all JSON files because of "heap out of memory" error.由于“堆内存不足”错误,第一个带有require循环无法读取所有 JSON 文件。 The second loop with readFile works.带有readFile的第二个循环有效。

If your file is empty, require will break.如果您的文件为空,则 require 将中断。 It will throw an error:它会抛出一个错误:

SyntaxError ... Unexpected end of JSON input. SyntaxError ... JSON 输入意外结束。

With readFileSync/readFile you can deal with this:使用readFileSync/readFile你可以处理这个:

let routesJson = JSON.parse(fs.readFileSync('./routes.json', 'UTF8') || '{}');

or:或者:

let routesJson
fs.readFile('./dueNfe_routes.json', 'UTF8', (err, data) => {
    routesJson = JSON.parse(data || '{}');
});

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM