はじめに
ノンブロッキングIOをちゃんと理解していないのであれば、Node.jsにあるSyncと付く関数は出来る限り使わない方が良いです。
もちろん、用意されているからには、何かしら有用性はあるため、ちゃんと理解しているのであれば、ガンガン使って良いと思います。
なぜ使ってはいけないか
JavaScriptはシングルスレッドで動作します。なので、一つずつしか処理は出来ず、同時に複数の処理が実行されることはありません。
Node.jsのfs.readFileSyncのように、「~Sysnc」となっている関数は、同期処理であり、ブロッキングIOです。そのため、fs.readFileSyncでファイルをディスクから読み取っている間もCPUを占有し、他の処理を実行することが出来ません。
ExpressなどのWebアプリケーションは、複数のリクエストを同時に扱う必要があります。なので、fs.readFileSyncでファイルを読み込んでいる間に、他のリクエストが待たされることになります。これがブロッキングIOです。
しかし、fs.readFileという「~Sync」が付いていない関数であれば、ディスクからファイルを読み取っている間は、他のリクエストが処理を行うことが可能となります。これがノンブロッキングIOです。
Webアプリケーション以外(electronなど)であっても、複数処理を同時に実行する場合があるため、fs.readFileSyncではなくfs.readFileを使用した方がよいでしょう。
サンプル
以下は、ブロッキングIOです。
const express = require('express');
const router = express.Router();
const fs = require('fs');
router.get('/', function(req, res, next) {
const content = fs.readFileSync('./test.txt', 'utf-8');
res.json({
result: content
});
});
module.exports = router;
fs.readFileSync
でファイルを読み込んでいる間は、他の処理が待たされます。
以下は、ノンブロッキングIOです。
const express = require('express');
const router = express.Router();
const fs = require('fs');
router.get('/', function(req, res, next) {
fs.readFile('./test.txt', 'utf-8', (err, content) => {
res.json({
result: content
});
});
});
module.exports = router;
fs.readFile
でファイルを読み込んでいる間は、CPUを占有しないため、他の処理が実行可能となります。
最後に
fs.readFileSync
の方が読み込んだ内容が戻り値で取得できるため、コールバックで取得するfs.readFile
と比べて簡単です。そのため、よくわかっていない人は、すぐにfs.readFileSync
を使ってしまいます。~~しかし、ブロッキングIOであるべき処理というのは、私の経験上あまり出会ったことはありません。(ブロッキングIOでも問題ない処理はあります。)~~なので、あくまでも私の考えですが、「~Sync」は使用しないで、できる限り「~Sync」が付いてない関数を使用した方がよいと思います。