2022年3月24日 Node.js入門 非同期ファイル読み書き
同期処理を行うとNode.jsの良さがなくなってしまうため利用は避けるべきです。
非同期処理の方法を見ていきます。
非同期ファイル読み込みをする場合
ファイルサイズが小さく後続処理も簡易な場合に利用します。
Promise 非同期処理の読み書き時にコールバックが多くなる問題の解消
util.promisifyメソッド
- utilを
require
します。 - util.promisifyメソッドを使用します。(Node.js v8以降の機能です)
- util.promisifyメソッドはコールバックを渡すとPromise化されたオブジェクトが取得できます。
- async awaitも使えるようになります。
util.promisifyメソッドを使った例
const fs = require("fs"); const path = require("path"); const util = require("util"); const readFile = util.promisify(fs.readFile); const writeFile = util.promisify(fs.writeFile); readFile(path.join(__dirname, "sample.txt"), "utf-8") .then((data) => { return writeFile(path.join(__dirname, "sample.txt"), "utf-8") }) .then(() => { console.log("OK"); }) .catch((error) => { console.log('error'); }); // 結果 OK
- util.promisifyメソッドがPromiseのオブジェクトを返しているためthenメソッドで
fulfilled
の結果が受け取れています。 - プロミスチェーンで最初のthenメソッドでfulfilled状態で返るため、二つ目のthenメソッドに処理が移っています。
async awaitで書き換えた例
const fs = require("fs"); const path = require("path"); const util = require("util"); const readFile = util.promisify(fs.readFile); const writeFile = util.promisify(fs.writeFile); (async function() { try { const data = await readFile(path.join(__dirname, "sample.txt"), "utf-8"); await writeFile(path.join(__dirname, "sample.txt"), "utf-8"); console.log(writeFile); console.log("OK"); } catch(error) { console.log(error.message); } })(); // 結果 OK
- async functionを即時実行関数で定義しています。
- async function直下でのawait式の挙動が得られるため非同期処理を同期処理のようにtry...catch構文を使用できています。
ストリーム
ストリームは大量のデータを小分けにして繰り返し処理を行います。一度に大量のデータを読み込まない事が特徴であり、メリットです。(リソースを一気に使ってしまわないようにできます)
※ファイルサイズが大きく後続処理が複雑な場合に利用します。
ストリームの種類
種類 | 説明 | 実装例 |
---|---|---|
Readable Stream | 読み込みができるストリーム | fs.ReadStream |
Writable Stream | 書き込みができるストリーム | fs.WriteStream |
Duplex Stream | 読み書き両方ができるストリーム | net.Socket |
Transform Stream | 読み書きのタイミングでデータ加工ができるストリーム | crypto.Chipher cryoto.Dechipher zlib.Gzip zlib.Gunzip |
ReadableStream ファイル読み込み
イベント
- data 小さなデータ一個読み込んだ時に発火
- end 全てのデータが読み終わった時に発火
メソッド
- pause() 読み込みを一時的に停止
- resume() データ読み込み開始, 再開
- pipe(stream) 次のストリームへデータを渡す