この記事は最終更新日から1年以上が経過しています。
@programming
投稿日 2022/7/8
更新日 2022/7/8 ✏
node-mysqlで結果一覧をfor await ofで捌く
node-mysqlモジュールを使ったMySQL DBへの問い合わせ結果をfor await...of
で扱う方法のメモです。
目次:
前提
node v16.14.2
node-mysql v2.18.1
以下のテスト用テーブルが既に存在すること:
mysql> select * from hugetable; +----+ | id | +----+ | 1 | | 2 | | 3 | | 4 | | 5 | | 6 | | 7 | | 8 | | 9 | +----+
サンプルコード
これまでのStreamを使った処理のpool.query()
な部分を AsyncIterator を返すモダンな処理に切り替えてfor await...of
で利用しています。
(async () => {
const mysql = require("mysql");
const { PassThrough } = require("stream");
const pool = mysql.createPool({
connectionLimit: 1,
host: 'localhost',
user: 'dbuser',
password: 'dbpass',
database: 'test',
});
const sql = "SELECT * FROM hugetable";
// AsyncIterableなDB問い合わせ結果を取得
const ait = pool
.query(sql)
.stream()
.pipe(new PassThrough({ objectMode: true }));
for await (const row of ait) {
console.log("row:", row);
// if (row.id === 3) break; // 途中でbreakすることも可能!
}
console.log("finish.");
pool.end();
})();
/* Console logs:
row: RowDataPacket { id: 1 }
row: RowDataPacket { id: 2 }
row: RowDataPacket { id: 3 }
row: RowDataPacket { id: 4 }
row: RowDataPacket { id: 5 }
row: RowDataPacket { id: 6 }
row: RowDataPacket { id: 7 }
row: RowDataPacket { id: 8 }
row: RowDataPacket { id: 9 }
finish.
*/
メリット
for await of
(AsyncIterator) を使うことで、Streamと同様に効率的に大量データを捌けるだけでなく、以下のようなメリットもあります:
- 中断処理がStreamよりも比較的簡単にコーディングできる
- Streamの場合よりもイベントループのブロッキングが少ない (筆者の環境でblocked-atを使った調査の結果)
参考
今回使ったサンプルコードはmysqljs/mysql/issues/2192のdougwilsonさんのコメントを参考にさせていただきました。