りゅうじの学習blog

学習したことをアウトプットしていきます。

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) 次のストリームへデータを渡す

参考

Udemy Node.js入門)