JavaScript/TypeScript で非同期処理を同期実行できる sync-actions というライブラリを公開しました。特に TypeScript では、定義された関数をタイプセーフな方法で呼び出すことができます。これは、非同期としてマークしたくない (またはできない) 関数内で非同期プロセスを実行する場合に使用することを目的としています。
https://github.com/koyopro/sync-actions
npmパッケージとして公開されていますので、npm install等でインストールしてください。
npm install sync-actions
Promise オブジェクトを返す非同期関数をdefineSyncWorker()に渡すことで、インターフェイスを定義し、launch()でワーカースレッドを開始できます。ワーカーを定義するファイルは他の処理ファイルとは別に作成されるものとします。
// worker.js import { defineSyncWorker } from "sync-actions"; export const { actions, worker } = defineSyncWorker(import.meta.filename, { ping: async () => { // Execute asynchronous process, await new Promise((resolve) => setTimeout(resolve, 1000)); // Return the result as a return value return "pong"; } }).launch();
// main.js import { actions, worker } from "./worker.js"; // You can execute asynchronous functions synchronously console.log(actions.ping()); // => "pong" is output after 1 second worker.terminate();
TypeScript では、defineSyncWorker で定義された関数をタイプセーフな方法で呼び出すことができます。
// worker.ts import { defineSyncWorker } from "sync-actions"; export const { actions, worker } = defineSyncWorker(import.meta.filename, { // By specifying the types of arguments and return values, type-safe calls are possible add: async (a: number, b: number): Promise<number> => { return a + b; } }).launch();
// main.ts import { actions, worker } from "./worker.js"; // Type-safe call actions.add(1, 2); // => 3 (number) // @ts-expect-error actions.add("1", 2); // => Argument of type 'string' is not assignable to parameter of type 'number' worker.terminate();
ここまでの内容はREADMEと同じなので、作成の背景を記載します。
Accel Record という ORM を開発しています。1 Accel Record は一般的な ORM とは異なり、同期インターフェースで DB アクセスを行うように設計されています。2 DB アクセスを同期的に実行する部分child_processで開始されるサブプロセス内で非同期処理を実行することで実現しました。 module.3 child_process の代わりに worker_threads を使用することで、実行時のオーバーヘッドを削減できると考えました。
Accel Record も、使い勝手の点では Ruby on Rails の Active Record に似ているように設計されており、将来的には CarrierWave のようなライブラリを作成したいと考えています。 CarrierWaveではレコード保存時に画像を外部ストレージサービス(AWS S3など)に保存できますが、Accel Recordでこれを実現するには画像アップロードなどの非同期処理を同期的に実行する必要があります。このプロセスはサブプロセスの代わりにworker_threadsを使用することでより高速に実行できると期待しています。
そこで、worker_threadsを使って非同期処理を同期実行するライブラリを探したことがあります。 synckit や deasync などのライブラリをいくつか見つけましたが、どれも私の側では期待どおりに機能しなかったため、独自のライブラリを作成することにしました。せっかくなのでTypeScriptでタイプセーフに使えるインターフェースを作ろうと思いました。
「Accel Record」の紹介: Active Record パターンを使用した TypeScript ORM ↩
新しい TypeScript ORM に同期 API を採用した理由 ↩
TypeScript での同期 DB アクセスのテクニック ↩
以上がJS/TSで非同期処理を同期実行するライブラリをリリースの詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。