🧘
Node.jsでシリアル通信などの待ち行列を実装する方法
この記事について
この記事では前のリクエストが完了するまで後のリクエストが待機する待ち行列のしくみをNode.jsで実装する方法を紹介します。待ち行列のしくみはシリアル通信のアプリケーションを開発する時など、リクエストを1つずつ順番に処理していく必要がある場合にとりわけ有用です。
おおまかな手順
おおまかな手順を下記に示します。
- コーディング
- 動作確認
コーディング
下記のコマンドを実行してコーディングの準備をします。
mkdir nodejs-serialport-queue
cd nodejs-serialport-queue
touch Deferred.js RequestQueue.js main.js
エディタでDeferred.jsを開いて下記の内容を入力します。
ポイントを下記に示します。Deferredについてはazuさんの JavaScript Promiseの本 の説明がとてもわかりやすいです。
- コンストラクターではPromiseを生成してresolveとrejectに外部からアクセスできるようにしています。
- resolveメソッドでは
this._resolve
を呼び出して値を送信しています。 - rejectメソッドでは
this._reject
を呼び出してエラーを通知しています。
続いてエディタでRequestQueue.jsを開いて下記の内容を入力します。
ポイントを下記に示します。
- enqueueメソッドではリクエストを作成して待ち行列に追加しています。
- リクエストの件数が1の時にprocessメソッドを呼び出しています。
- リクエストの完了を待機しています。
- processメソッドではリクエストの件数が1以上の時にループを実行しています。
- ループの最初では先頭のリクエストを取り出しています。
- リクエストの関数fnを実行して結果をDeferredのPromiseに送信しています。
- 完了時に先頭のリクエスト=現在処理中のリクエストを待ち行列から削除しています。
- エラーが発生した時にDeferredのPromiseにエラーを通知しています。
- エラー発生時も先頭のリクエスト=現在処理中のリクエストを待ち行列から削除しています。
続いてエディタでmain.jsを開いて下記の内容を入力します。
ポイントを下記に示します。
- main関数の最初ではリクエストの待ち行列を作成しています。
- リクエスト1を作成して待ち行列に追加しています。
- リクエスト2を作成して待ち行列に追加しています。
- リクエスト3を作成して待ち行列に追加しています。
- すべてのリクエストが待ち行列に追加されたことを出力しています。
- promise1の完了を待機しています。
- promise2のエラー発生を待機しています。
- promise3の完了を待機しています。
- 各リクエストの結果を出力しています。
動作確認
下記のコマンドを実行して出力を確認します。
node main.js
実行結果を下記に示します。
Request 1 start
All requests are enqueued
Request 1 end
Request 2 start
Request 2 end
Request 3 start
Request 3 end
promise1: resolve -> one
promise2: reject -> Error: two
promise3: resolve -> three
ポイントを下記に示します。
- Request1が完了するまでRequest2は待機しています。
- Request2でエラーが発生するまでRequest3は待機しています。
- Request 1 start は待ち行列に追加した時に出力されるので All requests are enqueued よりも先に表示されています
- すべてのリクエストが完了した時に promise1: resolve -> one などの結果が出力されています。
おわりに
紹介しておいて恐縮なのですが紹介した方法がエッジケースでもしっかりと動作するのかについては正直に申し上げて自分でも不安があります。より堅牢な作りにするのであればErlangのようなメッセージパッシングのモデルを参考にして実装した方が良いのではないかと考えています。もし良い方法をご存知の方がいらっしゃいましたらお気軽にコメントを頂ければ幸いです。最後まで読んでいただきありがとうございました。
Discussion