20201124のNode.jsに関する記事は8件です。

Docker環境でNodeJSのライブラリsharpを使用するときの darwin-x64 エラー

MacでNode.jsのライブラリsharpを使用するときに darwin-x64 エラーが発生しました。
Docker環境のため、sharpの公式ドキュメントで書いた対処方法ですぐ解決できなかったのではまりました。

/var/www/xxxxx/node_modules/sharp/lib/libvips.js:68
    throw new Error(`‘${vendorPlatformId}’ binaries cannot be used on the ‘${currentPlatformId}’ platform. Please remove the ‘node_modules/sharp/vendor’ directory and run ‘npm install’.`);

Error: ‘darwin-x64’ binaries cannot be used on the ‘linux-x64’ platform. Please remove the ‘node_modules/sharp/vendor’ directory and run ‘npm install’.
    at Object.hasVendoredLibvips (/var/www/xxxxx/node_modules/sharp/lib/libvips.js:68:13)
    at Object.<anonymous> (/var/www/xxxxx/node_modules/sharp/lib/constructor.js:7:22)
    at Module._compile (internal/modules/cjs/loader.js:1200:30)
    at Object.Module._extensions..js (internal/modules/cjs/loader.js:1220:10)
    at Module.load (internal/modules/cjs/loader.js:1049:32)
    at Function.Module._load (internal/modules/cjs/loader.js:937:14)
    at Module.require (internal/modules/cjs/loader.js:1089:19)
    at require (internal/modules/cjs/helpers.js:73:18)
    at Object.<anonymous> (/var/www/xxxxx/node_modules/sharp/lib/index.js:3:15)
    at Module._compile (internal/modules/cjs/loader.js:1200:30)

下記のように解決しました。
OS:macOS Catalina

1. nodeのバージョンを揃えます。

MacのnodeのバージョンとDocker環境のnodeバージョンとメジャーバージョンを揃えます。
例えば、
プロジェクトのnodeのバージョンが v14.xx.xx であれば、DockerfileでFROM node:14を指定。
※nodeのバージョンの制御にプロジェクト単位で設定できるnodenvの利用がおすすめです。

2. Dockerコンテナに入ってsharpを再インストール

$ docker ps
$ docker exec -it xxxxx bash
$ rm -rf node_modules/sharp
$ npm install --arch=x64 --platform=linux sharp

自分の環境では、targetの指定が不要でした。
$ npm install --arch=x64 --platform=linux --target=xx.xx.x sharp

参考:
https://github.com/lovell/sharp/blob/master/docs/install.md
https://sharp.pixelplumbing.com/install#common-problems
https://qiita.com/mame_daifuku/items/1dbdfbd4897b34df0d9f

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

【Win10】Node.jsのインストール

Node.jsのインストール

環境

OS: Windows10 Pro
Node.js: v12.18.3

手順

  1. Node.js公式サイトへアクセスして推奨版をDL
  2. DLしたmsiを実行
  3. コマンドプロンプトでバージョン確認

1.公式サイトへアクセス

https://nodejs.org/ja/へ移動して推奨版を選択します。
nodejs.org_ja_.png

2.DLしたmsiを実行

msi_bn.png

2-1.Node.jsのセットアップを開始

「Next」をクリックします。
node_1.png

2-2.ライセンスに同意

チェックを入れてから「Next」をクリックします。
node_2.png

2-3.インストール先フォルダの選択

インストール先を変更する場合はここで選択します。
node_3.png

2-4.セットアップのカスタム

機能をインストールする方法を選択します。
※デフォルトでnpmも一緒にインストールされます。
そのまま次へ。
node_4.png

2-5.ネイティブモジュール用のNode.jsセットアップツール

何もせずそのまま「Next」をクリックします。
node_5.png

2-6.Node.jsのインストールの準備

特に修正する点が無ければそのままInstallボタンを押下します。
node_6.png

2-7.インストール中

node_7.png

2-8.インストール完了

「Finish」をクリックします。
node_8.png

3.バージョン確認

コマンドを叩いてバージョンの確認が出来たらインストールが出来ている状態です。

バージョン確認
node --version
結果
v12.18.3
バージョン確認
npm --version
結果
6.14.6
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

【Win】Node.jsのインストール

Node.jsのインストール

環境

OS: Windows10 Pro
Node.js: v12.18.3

手順

  1. Node.js公式サイトへアクセスして推奨版をDL
  2. DLしたmsiを実行
  3. コマンドプロンプトでバージョン確認

1.公式サイトへアクセス

https://nodejs.org/ja/へ移動して推奨版を選択します。
nodejs.org_ja_.png

2.DLしたmsiを実行

msi_bn.png

2-1.Node.jsのセットアップを開始

「Next」をクリックします。
node_1.png

2-2.ライセンスに同意

チェックを入れてから「Next」をクリックします。
node_2.png

2-3.インストール先フォルダの選択

インストール先を変更する場合はここで選択します。
node_3.png

2-4.セットアップのカスタム

機能をインストールする方法を選択します。
※デフォルトでnpmも一緒にインストールされます。
そのまま次へ。
node_4.png

2-5.ネイティブモジュール用のNode.jsセットアップツール

何もせずそのまま「Next」をクリックします。
node_5.png

2-6.Node.jsのインストールの準備

特に修正する点が無ければそのままInstallボタンを押下します。
node_6.png

2-7.インストール中

node_7.png

2-8.インストール完了

「Finish」をクリックします。
node_8.png

3.バージョン確認

コマンドを叩いてバージョンの確認が出来たらインストールが出来ている状態です。

バージョン確認
node --version
結果
v12.18.3
バージョン確認
npm --version
結果
6.14.6
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

【Node.js csvファイルを一行ずつストリーミング】

Streamの使い方を試すためにcsvファイルを一行ずつストリーミングして表示するものを作ってみることにした。

今回はconsoleに表示するだけなので、読み込みstreamだけ使う。

readlineモジュールと読み込みStreamを組み合わせる。

const fs = require('fs');
const readline = require('readline');

//index.csvは50行あることにする
var fileName = 'index.csv';

const rs = fs.createReadStream(fileName, {encoding: "utf8"});
const rl = readline.createInterface({ input: rs });

let count = 0;
rl.on('line', (army) => {
    count++;
    console.log(army + '\n');
  });
rl.on('close', () => {
    console.log(count); // index.csvは50行なので50が表示される
});

外部ファイルに書き込みたい場合は書き込みstreamも組み合わせる。

以下の記事を参考にさせていただきました。

https://qiita.com/tarotaro1129/items/93521afd693796eb2cfa

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

DockerでNode.js環境構築

概要

DockerfileDocker-composeを使って簡単にnode.jsの環境を作る。

ディレクトリ構造

node_app
├─ Dockerfile
└─ docker-compose.yml

Dockerfile の記載

Dockerfile
#イメージを指定
FROM node:12.4.0-alpine

# 環境変数を定義
ENV NODE_ENV=development

# 雛形パッケージのインストール
RUN npm install -g express-generator

# 初期カレントディレクトリ
WORKDIR /app

# 開放ポート
EXPOSE 3000

docker-compose.yml の記載

docker-compose.yml
version: '3.7'
services:
  app:
    build:
      context: .
      dockerfile: Dockerfile
    container_name: node
    volumes:
      - ./app:/app
    ports:
      - "8080:3000"

context ディレクトリの指定 「 . 」 で同じディレクトリ

container_name コンテナネームの指定

volumes データーのマウント共有の指定 左がホスト 右がコンテナ

ports コンテナとホストのポートをつなげる指定

Dockerfile からイメージのビルド

$ docker-compose build

コンテナを生成、起動

-d (デタッチ オプション)でバックグラウンドで起動

$ docker-compose up -d

コンテナに接続

-i(--interactive)標準入力を設定させ、コマンドを対話的にする
-t(--tty)疑似ターミナルの割り当て

$ docker exec -it [CONTAINER_ID] bash

express-generator で雛形の作成

今回はテンプレートエンジンはejsを使用

# express --view=ejs /app

パッケージのインストール

# npm install

サーバーを起動

# npm start

local hostに接続して Welcome to Express! と表示されれば完成です。

参考本

Docker ドキュメント
Docker/Kubernetes 実践コンテナ開発入門

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

院内SEへの問い合わせをAIで!FAQ-botの作り方

最近私の勤務している病院が移転したことにより、建物が大きくなり部署も増え、職員も増えたので問い合わせの量も増えました。しかしシステム課の人員は移転前と同じままです。明らかに業務量が目に見えて増えるようになりました。人員はすぐには増やせないのでこの人数で対応を行わなければなりません。

そんな中移転作業の振り返りで、AIで業務負担を軽減できないかなぁと話が挙がりました。AIは最近のニュースで何度も話題なっていて興味はあったのですが、大企業とか大規模なデータを持っている会社しかできないだろうと思っていました。

しかし、同じ沖縄の情シスの方がDialogFlowというサービスを使ったAIを構築していると伺いました。調べてみると、そのDialogFlowを応用して、AIを使ったチャットボットシステムが意外と簡単にしかも無料で作れました。

今回はそのAI-FAQ-botの概要と、その作成方法についてご紹介いたします。

FAQ-botの概要

まず今回のbotはLINE株式会社の社員さんが紹介している記事を参考にして作成しました。この記事で私が構築したい内容がほぼ決まり、また構築方法もほとんど載っていたので大変参考になりました。

作成したbotはどんどん賢くなるチャットボットをテーマとして作成しました。ユーザーからの質問に答え、分からないことは管理者である院内SEに回答を伺い、その回答内容を学習して賢くなっていくbotになります。

具体的には

  1. ユーザーからの質問で用意されているものなら自動で返答する
  2. 用意されていない質問だと、管理者(院内SE)に回答を促す
  3. 管理者(院内SE)が回答を行うと、回答内容をユーザーに返答する
  4. 管理者(院内SE)が回答した内容をbotが学習し、次回以降の同じ質問は自動で返答する

このような流れで動いています。

動作図

output (1).gif

ユーザーと管理者が同じ画面なので分かりにくいですが、「テスト」、「よろしく」というユーザーからのメッセージに対してはbotが自動的に答えています。しかし「ありがとう」というユーザーからのメッセージには管理者に回答を促し、管理者の回答内容をユーザーに返すといった動作になっています。

システム図

今回構築したシステムは以下のサービスを組み合わせています。

  • LINE
  • DialogFlow
  • Heroku

system-diagram.png

ユーザーはLINEを通してシステム課への問い合わせを行います。問い合わせの内容はクラウド上にあるサーバー(Heroku)のチャットボットプログラムに送られます。

その後、DialogFlowという自然言語処理サービスにより、問い合わせの意図を分析します。その分析した結果により回答できる場合は自動的に返答し、回答できない場合は管理者のLINEアカウントへ回答を促すシステムとなっています。

動作フロー

システムの動きの流れとしては以下のようになっています。左が自動応答で右が管理者からの回答が必要な場合の動きです。

image-20201110215912825.png

まず自動応答の場合ですが、ユーザーが質問を送るとチャットボットPGはDialogFlowに質問意図の解析を依頼します。意図を特定出来たら対応するスキルで処理を行い、その結果をユーザーに返すことで自動応答を実現しています。

管理者から回答を行う場合、ユーザーからの質問をDialogFlowで意図解析するまでは同じですが、DialogFlowで意図が分からなかった場合、チャットボットPGは管理者へエスカレーションして管理者(院内SE)に問い合わせます。管理者が回答を行うとその回答内容をユーザーにそのまま転送を行います。さらにその回答内容をDialogFlowに学習させることで次回以降の同じ質問は自動で答えられるようにしていく仕組みになっています。

各種システムについて

今回は無料で構築するためにそれぞれ無料の範囲内で動かしていますが、制限があるので、その制約事項とともに各システムについてご説明します。

LINE

まずはLINEです。もうこれはメジャーなんで説明不要なくらい普及しているので、職員に使ってもらえると思い採用しました。しかしスマホで通常使っているLINEではなく、LINE公式アカウントというのを作成して使用しています。

LINE公式アカウントとはLINEで使っている機能を使え、LINEユーザーに情報発信や販促などを行いやすいものとなっています。そして今回の目的であるbotとして使うために必須のものとなっています。

そんなLINE公式アカウントですが、プランが3種類あり以下のように月額料金が変わります。

line-pran.png

無料で使っているとメッセージ数が1,000通に制限されてしまいます。カウントされるメッセージは、botから返答されるメッセージも基本的にカウントされますし、LINE公式アカウントから配信できるメッセージもカウントされるので上限に達しないように注意が必要です。

DialogFlow

次にDialogFlowですが、このサービスはGoogleが提供している言語解析エンジンで様々なサービス連携することが可能です。LINEはもちろん、SlackやWeb、Androidスマホなどの「OK,Google」でも連携することが可能です。

こちらもいくつかのプランがあり、今回は無料で使っていますが、無料プランでも今回導入しようと検討している範囲では問題なく使えそうなくらい制約事項があまりないです。

例えば、botが1分当たりに反応する回数が180回までだったり、反応する例文数が2,000までだったりと広めに範囲が取られているので、とりあえずは安心して使っていくことができそうです。

Heroku

次にHerokuです。HerokuはPaaS(Platform as a Service)と呼ばれるサービスの一種で、サーバー、OS、データベース、プログラム実行環境を稼働させることができます。私も以前個人開発で作ったWebサービスをHerokuで動かしていたので始めやすかったです。個人開発のようなスモールサービスで使うこともできるのでお勧めです。

そんなHerokuにもいくつかのプランがあり、無料プランでは制限があり使用限度時間が1か月あたり550時間になります。クレジットカードを登録すると1000時間までになるので1日24時間×31日=744時間で常時起動が可能となります。しかしもう一つ制限があり、30分間アクセスがなければ自動的にスリープに入り、次の応答までに時間がかかってしまいます。私の環境だとスリープ後にLINEメッセージを送ると返信まで20秒前後かかりました。こちらはherokuのアドオンや外部サービスで定期的にアクセスするジョブなどを実行すれば回避できます。

チャットボット

肝心なプログラムですが、こちらはLINE株式会社の社員さんが公開している記事を参考にして作りました。

https://engineering.linecorp.com/ja/blog/how-to-make-better-chatbot/

環境構築についてもqiitaでいくつかの記事を公開しているので、それを参考にして構築することができました。GitHubで公開されているソースコードに少し修正を入れて自分の環境で使えるようにしていますので、ご興味がある方はご覧ください。GitHub

動作フローのところで説明したスキルですが、具体的にこのボットは以下の3つのスキルで構成されています。

  • robot-response

意図が特定できた問い合わせに対して、用意されている回答を自動的にユーザーに返すスキル意図が特定できた問い合わせに対して、用意されている回答を自動的にユーザーに返すスキル

  • escalation

意図が特定できなかった問い合わせに対し、管理者に回答してもらうように促す。

  • human-response

エスカレーションされてきた問い合わせ内容に対し、管理者からの回答内容をユーザーに返信し、botに学習させる。

導入手順

ここまででボットの概要を説明してきましたが、いかがでしたでしょうか?院内SEだけではなくそのほかの部署、事務部や総務、経理などよく問い合わせを受ける部署で役に立つと思います。またこのシステムは最近話題になってきているノンコーディングで構築できています。プログラムコードはありますが、公開しているコードを使用しているのでほぼ手を加えていません。そして運用行う上で例文や回答の追加はプログラムを修正する必要がなく、Web上のGUI画面で追加することができるのでプログラムを知らない方でも運用ができます。

ここからは具体的に構築手順について説明していきます。私のブログの方で具体的な方法を説明していますので、興味がある方は是非ご覧ください。(申し訳ありませんが有料となります)
https://hospital-se.work/create-ai-faq-bot/

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

npmを特定のポート番号で動かしたい

ご無沙汰してます、おおのんです。
一時的に指定したポート番号でnuxtアプリを立ち上げる方法。

ターミナルでnuxtアプリを5000番で動かす。
npm run dev -- --port 5000

はい。

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

Node.jsのEventEmitterの使い方

はじめに

Node.jsではファイルの読み込みやHTTPリクエストなど、非同期で行われる処理があります。
この非同期処理の終了を検知する方法の一つとして、EventEmitterが用意されています。
このEventEmitterについてまとめます。

環境

  • Node.js 12.18.3

EventEmitterの使い方

ローカルに保存されているファイルを読み込み、終了後に後続の処理を実行するサンプルを作り、まとめていきたいと思います。

EventEmitterの呼び出し

EventEmitterクラスはNode.jsのeventsモジュールに定義されています。

// eventsモジュールのEventEmitterの参照を取得
const { EventEmitter } = require('events');

ファイル読み込み関数の作成

続いてファイルを読み込む処理を書いていきます。

// 〜略〜

// fsモジュールの読み込み
const fs = require('fs');

// ファイルを読み込む処理
const readFile = () => {
    // EventEmitterのインスタンス生成
    const emitter = new EventEmitter();

    // target.txtファイルを読み込む
    fs.readFile('target.txt', 'utf8', (err, data) => {
        // エラー発生時、errorイベントを発行し、処理を終了する
        if (err) {
            return emitter.emit('error', err);
        }
        // 読み込みが完了したら、finishイベントを発行し、ファイルの中身を渡す
        emitter.emit('finish', data);
    });

    // この関数にメソッドチェーンできるようにEventEmitterのインスタンスを返す
    return emitter;
};

この関数で使っているemit()が、イベントを発行するメソッドです。
emit()に第1引数で渡したイベントが発行され、次に記述するon()で登録されたリスナーに通知される仕組みです。(第2引数以降はそのままリスナー関数に引数として渡されます)

readFile関数内でやっていることを、日本語でまとめます。
1. EventEmitterのインスタンスを生成
2. target.txtファイルを読み込む
3. ファイル読み込み中にエラーが発生した場合、errorイベントを発行
4. ファイル読み込み完了後、finishイベントを発行

readFileの呼び出し

次にこの関数を呼び出して、実際にファイルを読み込む処理、発行されるイベントにリスナーを登録する処理を追記します。

// 〜略〜

// readFile関数を呼び出し、各イベントに対してリスナーを登録
readFile()
    .on('finish', (data) => console.log('finishイベント', data))
    .on('error', (err) => console.error('errorイベント', err));

なお、EventEmitterでerrorイベントemit()する場合は、呼び出し時に必ずon('error')を指定するようにしてください。
errorイベント発行時にリスナーが登録されていない場合、Unhandled 'error' eventエラーで処理が落ちてしまいますので、ご注意ください。

実行

まずはそのまま実行します。

実行結果
errorイベント [Error: ENOENT: no such file or directory, open 'target.txt'] {
  errno: -2,
  code: 'ENOENT',
  syscall: 'open',
  path: 'target.txt'
}

ちゃんとon('error')で登録したリスナーが動き、「そんなファイルないよ」とエラーを出力してくれました。

次に実行ファイルと同じディレクトリに、次の内容でtarget.txtを作成し、

target.txt
target

実行します。

実行結果
finishイベント target

今度はon('finish')で登録したリスナーが動き、ファイルの中身を出力してくれました。

その他のメソッドについて

once

onceは、onと同じくイベントに対してリスナーを登録するメソッドですが、一度イベントが通知されると解除されます。

removeListener(event, listener)

登録済みのリスナーを解除するメソッドです。

EventEmitterクラスの拡張

上記のreadFile()関数をクラス化し、より複雑な処理をさせたい場合は、EventEmitterクラスを継承して独自のメソッドを追記することができます。

先程作成した関数をクラスにし、読み込むファイルを複数追加できるように書き換えます。

const { EventEmitter } = require('events');
const fs = require('fs');

class ReadFile extends EventEmitter {

    constructor() {
        // EventEmitterのコンストラクタ呼び出し
        super();
        // 検索対象のファイル名
        this.files = [];
    }

    // 読み込み対象のファイルを追加する処理
    addFile(file) {
        this.files.push(file);
        return this;
    }

    // ファイル読み込み
    readFile() {
        this.files.forEach((file) => {
            fs.readFile(file, 'utf8', (err, data) => {
                // エラー発生時、errorイベントを発行し、処理を終了する
                if (err) {
                    return this.emit('error', err);
                }
                // 読み込みが完了したら、finishイベントを発行し、ファイルの中身を渡す
                this.emit('finish', data);
            });
        });

        return this;
    }
}

次に上のクラスを使ってファイルを読み込む処理を追記します。

// ReadFileのインスタンス生成
const rf = new ReadFile();
// 読み込み処理
rf.addFile('target.txt')
    .addFile('dummy.txt')
    .readFile()
    .on('finish', (data) => console.log('finishイベント', data))
    .on('error', (err) => console.error('errorイベント', err));

今回は先程作成したtarget.txtに加えて、わざとエラーを起こすように存在しないファイルdummy.txtも読み込み対象に加えています。

それでは実行してみます。

実行結果
errorイベント [Error: ENOENT: no such file or directory, open 'dummy.txt'] {
  errno: -2,
  code: 'ENOENT',
  syscall: 'open',
  path: 'dummy.txt'
}
finishイベント target

dummy.txtを読み込むときはerrorイベントが発行され、target.txtを読み込んだときはfinishイベントが発行されてファイルの中身が表示されました。

このクラスを使ったパターンはNode.jsのServerクラスなどでも使われているようです。

より大きなファイルを読み込むサンプル

今度はEventEmitterを継承しているStreamを使って、先程のサンプルよりも大きいファイルを読み込むサンプルを作成していきたいと思います。

大きなファイルを読み込む場合、先程のサンプルのように「すべてのデータをバッファに読み込んでから後続の処理をする」という方式をとっていると、なかなか処理が帰ってこず、不安になったり、メモリを一気に消費してしまって、負荷の高い処理となってしまう、ということが起きてしまいます。

それを解決するためにStreamを使います。
Streamはデータが読み込まれるたびに通知されるので、すべてのデータの読み込みを待つことなく、処理を開始することができます。

サンプルの作成

巨大なテキストファイルをすべて大文字にして出力する、というサンプルを作成します。

// streamモジュールからTransform streamを取得
const { Transform } = require('stream');
const fs = require('fs');

// Transform streamを継承したクラスを作成
class ToUpper extends Transform {
    constructor() {
        super();
    }

    // chunkが送られてくるたびに実行
    _transform(chunk, encoding, callback) {
        // 内部のバッファにすべて大文字にした文字列をpush
        this.push(chunk.toString().toUpperCase());
        callback();
    }
}

// 置換クラスのインスタンス生成
const toUpper = new ToUpper();
toUpper.on('data', (chunk) => console.log(chunk.toString() + '\n\n\n'));

// Read streamを使って対象ファイルを読み込み
const rs = fs.createReadStream('target.txt');
// 一定量読み込み、次の処理にchunkを渡す
rs.on('data', (chunk) => toUpper.write(chunk));

上記のサンプルでは、まずTransform streamを実装するため、stream.Transformを継承したクラスを作成します。今回の趣旨からは外れるため細かな説明は省きますが、データが送られてくるたびに_transform()が実行され、内部のバッファに書き換えたデータをpushします。

次にfsモジュールのcreateReadStream()を使って、target.txtを読み込むRead streamを作成します。Read streamは一定量のデータを読み込んだら、dataイベントを発行します。今回登録しているリスナーでは、ToUpperクラスのインスタンスに読み込んだデータを渡す処理をしています。

こちら実行すると、chunkごとに改行で区切られ、大文字に変換されたテキストデータが出力されます。(サイズが大きいためこちらには一部のみ記載します)

SUSPENDISSE VITAE FRINGILLA LECTUS. FUSCE VENENATIS ENIM MAURIS, AC VIVERRA ENIM PORTA ID. SUSPENDISSE AUCTOR LECTUS EU ORCI SCELERISQUE SODALES. MORBI VESTIBULUM BLANDIT EGESTAS. NUNC EGET URNA IN JUSTO ORNARE FAUCIBUS. SUSPENDISSE ELEMENTUM LOREM NON TORTOR DIGNISSIM, SED EFFICITUR LOREM VOLUTPAT. QUISQUE LAOREET VESTIBULUM EST NON DAPIBUS. VESTIBULUM SIT AMET MAGNA EGET LACUS MOLLIS PELLENTESQUE.
DUIS MOLLIS LIGULA MI, AC SCELERISQUE DUI DAPIBUS EU. PRAESENT AC VENENATIS LECTUS, VITAE RHONCUS ELIT. NUNC SAGITTIS TURPIS QUIS DUI LOBORTIS, SED SOLLICITUDIN ERAT VEHIC



ULA. ETIAM A VENENATIS IPSUM, UT ELEMENTUM MAURIS. AENEAN ELEIFEND GRAVIDA VENENATIS. DONEC LOBORTIS NON SAPIEN AC TEMPOR. ALIQUAM TRISTIQUE JUSTO LIGULA, VITAE GRAVIDA ODIO MOLESTIE VEL. PRAESENT TRISTIQUE LECTUS EST, IN ORNARE ODIO FACILISIS UT. DONEC A EGESTAS QUAM. INTEGER TEMPUS SCELERISQUE ELIT, ET CONSEQUAT LACUS TEMPUS MATTIS.
LOREM IPSUM DOLOR SIT AMET, CONSECTETUR ADIPISCING

なお、Stream同士の接続はpipe()を使うことで、もう少しスマートに同じことができます。

// 〜略〜
// Read streamを使って対象ファイルを読み込み
const rs = fs.createReadStream('target.txt');
// 一定量読み込み、次の処理にchunkを渡す
rs.pipe(toUpper);

最後に

あまりEventEmitterを直接いじる、ということはないと思うのですが、
普段何気なく使っているNodeモジュールやパッケージの内部ではこういった処理が使われていたんだな、と知ることができました。

参考書籍

Mario Casciaro、Luciano Mammino 著、武舎 広幸、阿部 和也 訳(2019)『Node.jsデザインパターン 第2版 』O'Reilly Japan, Inc.

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む