ホームページ > ウェブフロントエンド > jsチュートリアル > JS/TSで非同期処理を同期実行するライブラリをリリース

JS/TSで非同期処理を同期実行するライブラリをリリース

Susan Sarandon
リリース: 2024-12-21 02:44:09
オリジナル
779 人が閲覧しました

Released a Library for Synchronous Execution of Asynchronous Processes in JS/TS

JavaScript/TypeScript で非同期処理を同期実行できる sync-actions というライブラリを公開しました。特に TypeScript では、定義された関数をタイプセーフな方法で呼び出すことができます。これは、非同期としてマークしたくない (またはできない) 関数内で非同期プロセスを実行する場合に使用することを目的としています。

特徴

  • Node.jsのworker_threadsを利用します
    • 非同期プロセスはサブスレッドで実行され、メインスレッドはその完了を同期的に待機します。
  • タイプセーフな関数呼び出し
    • TypeScript では、定義された関数の型情報を利用できます。
  • ネイティブ ESM として公開
    • CommonJS をサポートしないことでシンプルになっています。

リポジトリ

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でタイプセーフに使えるインターフェースを作ろうと思いました。

内部詳細の詳細

  • worker_threadsで起動したサブスレッドの非同期処理が完了するまで、メインスレッドはAtomic.wait()でブロックされます。
  • MessageChannel はスレッド間の通信に使用されます。 synckit のソース コードは、実装のこの部分で非常に役立ちました。
  • worker_threads でワーカーを起動する場合、.ts ファイルを .js にトランスパイルする必要があります。その部分にはesbuildを使用しています。
  • Worker を起動するときに、トランスパイルされたソース コードを文字列として Worker に渡して実行したいと考えましたが、私の環境では正しく動作しませんでした。ここが一番苦労した部分です。最終的に、node_modules の下にファイルを書き込み、そのパスをワーカーに渡しました。この方法が最も安定していることが判明しました。

  1. 「Accel Record」の紹介: Active Record パターンを使用した TypeScript ORM ↩

  2. 新しい TypeScript ORM に同期 API を採用した理由 ↩

  3. TypeScript での同期 DB アクセスのテクニック ↩

以上がJS/TSで非同期処理を同期実行するライブラリをリリースの詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。

ソース:dev.to
このウェブサイトの声明
この記事の内容はネチズンが自主的に寄稿したものであり、著作権は原著者に帰属します。このサイトは、それに相当する法的責任を負いません。盗作または侵害の疑いのあるコンテンツを見つけた場合は、admin@php.cn までご連絡ください。
著者別の最新記事
人気のチュートリアル
詳細>
最新のダウンロード
詳細>
ウェブエフェクト
公式サイト
サイト素材
フロントエンドテンプレート