「非同期ローカル ストレージ」というフレーズを聞くと、何を思い浮かべますか?最初は、ブラウザベースのローカル ストレージの魔法のような実装を指していると思うかもしれません。しかし、この仮定は正しくありません。非同期ローカル ストレージは、ブラウザー関連でも一般的なストレージ メカニズムでもありません。おそらく、あなたが使用した 1 つまたは 2 つのライブラリが内部で使用されていると思われます。多くの場合、この機能により、煩雑なコードを扱う必要がなくなります。
非同期ローカル ストレージとは何ですか?
非同期ローカル ストレージは Node.js で導入された機能で、最初はバージョン v13.10.0 と v12.17.0 で追加され、その後 v16.4.0 で安定しました。これは async_hooks モジュールの一部であり、Node.js アプリケーションで非同期リソースを追跡する方法を提供します。この機能により、複数の非同期関数が明示的に渡さずにアクセスできる共有コンテキストを作成できます。コンテキストは、AsyncLocalStorage インスタンスの run() メソッドに渡されるコールバック内で実行されるすべての (および唯一の) 操作で使用できます。
AsyncLocalStorage の使用パターン
例に入る前に、使用するパターンについて説明しましょう。
初期化
import { AsyncLocalStorage } from "async_hooks"; import { Context } from "./types"; export const asyncLocalStorage = new AsyncLocalStorage<context>(); // export const authAsyncLocalStorage = new AuthAsyncLocalStorage<authcontext>() </authcontext></context>
上記のモジュールでは、AsyncLocalStorage のインスタンスを初期化し、それを変数としてエクスポートします。
使用法
asyncLocalStorage.run({ userId }, async () => { const usersData: UserData = await collectUsersData(); console.log("usersData", usersData); }); // (method) AsyncLocalStorage<unknown>.run<promise>>(store: unknown, callback: () => Promise<void>): Promise<void> (+1 overload) </void></void></promise></unknown>
run() メソッドは 2 つの引数を取ります。共有するデータを含むストレージと、ロジックを配置するコールバックです。その結果、コールバック内のすべての関数呼び出しでストレージにアクセスできるようになり、非同期操作全体でシームレスなデータ共有が可能になります。
async function collectUsersData() { const context = asyncLocalStorage.getStore(); }
コンテキストにアクセスするには、インスタンスをインポートし、asyncLocalStorage.getStore() メソッドを呼び出します。素晴らしい点は、初期化中に Context タイプを AsyncLocalStorage に渡したため、 getStore() から取得したストレージが型指定されていることです: new AsyncLocalStorage
認証コンテキストとしての非同期ローカル ストレージ
認証システムのない Web アプリケーションは存在しません。認証トークンを検証し、ユーザー情報を抽出する必要があります。ユーザー ID を取得したら、それをルート ハンドラーで利用できるようにして、それぞれのハンドラーでコードが重複するのを避けたいと考えています。 AsyncLocalStorage を利用して、コードをクリーンに保ちながら認証コンテキストを実装する方法を見てみましょう。
この例では fastify を選択しました。
ドキュメントによると、fastify は次のとおりです。
Node.js 用の高速でオーバーヘッドの低い Web フレームワーク
わかりました、始めましょう:
- fastify をインストールします:
import { AsyncLocalStorage } from "async_hooks"; import { Context } from "./types"; export const asyncLocalStorage = new AsyncLocalStorage<context>(); // export const authAsyncLocalStorage = new AuthAsyncLocalStorage<authcontext>() </authcontext></context>
- 認証コンテキストのタイプを定義します。
asyncLocalStorage.run({ userId }, async () => { const usersData: UserData = await collectUsersData(); console.log("usersData", usersData); }); // (method) AsyncLocalStorage<unknown>.run<promise>>(store: unknown, callback: () => Promise<void>): Promise<void> (+1 overload) </void></void></promise></unknown>
- AsyncLocalStorage のインスタンスを初期化し、それを変数に割り当て、その変数をエクスポートします。関連するタイプを忘れずに渡します: new AsyncLocalStorage
()。
async function collectUsersData() { const context = asyncLocalStorage.getStore(); }
- Fastify インスタンスを初期化し、エラー処理用のユーティリティを追加します。
npm install fastify
ここからが非常に重要な部分です。 authAsyncLocalStorage.run() メソッドでハンドラーをラップするための onRequest フックを追加します。
type Context = Map;
検証が成功した後、authAsyncLocalStorage から run() メソッドを呼び出します。ストレージ引数として、トークンから取得した userId を含む認証コンテキストを渡します。コールバックでは、done 関数を呼び出して Fastify ライフサイクルを続行します。
非同期操作を必要とする認証チェックがある場合は、それらをコールバックに追加する必要があります。ドキュメントによると、これは次の理由によるものです。
done コールバックは、async/await を使用する場合、または Promise を返す場合には使用できません。この状況で完了コールバックを呼び出すと、予期しない動作が発生する可能性があります。ハンドラーの重複呼び出し
これがどのように見えるかの例を次に示します:
import { AsyncLocalStorage } from "async_hooks"; import { Context } from "./types"; export const authAsyncLocalStorage = new AsyncLocalStorage<context>(); </context>
この例では、保護されたルートが 1 つだけあります。より複雑なシナリオでは、特定のルートのみを認証コンテキストでラップする必要がある場合があります。そのような場合は、次のいずれかを行うことができます:
- 特定のルートにのみ適用されるカスタム プラグインで onRequest フックをラップします。
- onRequest フック自体内にルート区別ロジックを追加します。
よし、コンテキストが設定されたので、保護されたルートを定義できるようになりました。
import Fastify from "fastify"; /* other code... */ const app = Fastify(); function sendUnauthorized(reply: FastifyReply, message: string) { reply.code(401).send({ error: `Unauthorized: ${message}` }); } /* other code... */
コードは非常に簡単です。 authAsyncLocalStorage をインポートし、userId を取得し、UserRepository を初期化し、データを取得します。このアプローチにより、ルート ハンドラーがクリーンかつ集中的に保たれます。
Next.js が非同期ローカル ストレージをどのように使用するかを調べる
この例では、Next.js から Cookie ヘルパーを再実装します。でもちょっと待ってください。これは AsyncLocalStorage に関する投稿ですよね?では、なぜクッキーについて話しているのでしょうか?答えは簡単です。Next.js は AsyncLocalStorage を使用してサーバー上の Cookie を管理します。そのため、サーバー コンポーネント内の Cookie を読み取るのは次のように簡単です。
import Fastify from "fastify"; import { authAsyncLocalStorage } from "./context"; import { getUserIdFromToken, validateToken } from "./utils"; /* other code... */ app.addHook( "onRequest", (request: FastifyRequest, reply: FastifyReply, done: () => void) => { const accessToken = request.headers.authorization?.split(" ")[1]; const isTokenValid = validateToken(accessToken); if (!isTokenValid) { sendUnauthorized(reply, "Access token is invalid"); } const userId = accessToken ? getUserIdFromToken(accessToken) : null; if (!userId) { sendUnauthorized(reply, "Invalid or expired token"); } authAsyncLocalStorage.run(new Map([["userId", userId]]), async () => { await new Promise((resolve) => setTimeout(resolve, 2000)); sendUnauthorized(reply, "Invalid or expired token"); done(); }); }, ); /* other code... */
私たちは next/headers からエクスポートされた cookie 関数を使用します。この関数は、cookie を管理するためのいくつかの方法を提供します。しかし、これは技術的にどのようにして可能なのでしょうか?
さあ、再実装を開始する時が来ました。」
まず、この例は、Lee Robinson による素晴らしいビデオと Next.js リポジトリから得た知識に基づいていることを述べておきたいと思います。
この例では、サーバー フレームワークとして Hono を使用します。これを選んだ理由は 2 つあります:
- 試してみたかっただけです。
- JSX に対する確実なサポートを提供します。
まず Hono をインストールします:
import { AsyncLocalStorage } from "async_hooks"; import { Context } from "./types"; export const asyncLocalStorage = new AsyncLocalStorage<context>(); // export const authAsyncLocalStorage = new AuthAsyncLocalStorage<authcontext>() </authcontext></context>
次に、Hono を初期化し、ミドルウェアを追加します。
asyncLocalStorage.run({ userId }, async () => { const usersData: UserData = await collectUsersData(); console.log("usersData", usersData); }); // (method) AsyncLocalStorage<unknown>.run<promise>>(store: unknown, callback: () => Promise<void>): Promise<void> (+1 overload) </void></void></promise></unknown>
このコードは、Fastify サンプルのミドルウェアに似ていますね。コンテキストを設定するには、cookie モジュール (cookie 関数のカスタムの単純な実装) からインポートされる setCookieContext を利用します。 setCookieContext 関数に従って、インポート元のモジュールに移動しましょう:
async function collectUsersData() { const context = asyncLocalStorage.getStore(); }
setCookieContext 関数 (その戻り値を Hono ミドルウェアの cookieAsyncLocalStorage.run() に渡しました) は、hono コンテキストを表す c パラメーターから Cookie を抽出し、Cookie を管理するためのユーティリティ関数を提供するクロージャーとそれらをバンドルします。
当社の Cookie 機能は、next/headers の Cookie の機能を複製します。 cookieAsyncLocalStorage.getStore() メソッドを利用して、呼び出し時に cookieAsyncLocalStorage.run() に渡されるのと同じコンテキストにアクセスします。
Next.js 実装の動作を模倣するという約束で、cookie 関数の戻り値をラップしました。バージョン 15 より前では、この関数は同期でした。現在の Next.js コードでは、次の簡略化された例に示すように、Cookie によって返されるメソッドが Promise オブジェクトにアタッチされます。
npm install fastify
もう 1 つ言及する価値がある点は、この場合、cookies.setCookie と cookies.deleteCookie を使用すると、サーバー コンポーネントに Cookie を設定するときに Next.js で観察される動作と同様に、常にエラーがスローされることです。元の実装では、setCookie または deleteCookie を使用できるかどうかは、RequestStore と呼ばれるストレージ (これは AsyncLocalStorage の実装であり、Cookie も保存されます) に保存されているフェーズ (WorkUnitPhase) プロパティに依存するため、このロジックをハードコードしました。ただし、このトピックについては別の投稿に適しています。この例を単純にするために、WorkUnitPhase.
のシミュレーションを省略しましょう。次に、React コードを追加する必要があります。
- アプリ コンポーネントを追加します。
type Context = Map;
- Cookie を管理するためのコンポーネントを追加します。
import { AsyncLocalStorage } from "async_hooks"; import { Context } from "./types"; export const authAsyncLocalStorage = new AsyncLocalStorage<context>(); </context>
Cookie の使用法は、Next.js React サーバー コンポーネントでの使用方法と似ています。
- テンプレートをレンダリングするルート ハンドラーを追加します。
import Fastify from "fastify"; /* other code... */ const app = Fastify(); function sendUnauthorized(reply: FastifyReply, message: string) { reply.code(401).send({ error: `Unauthorized: ${message}` }); } /* other code... */
私たちのテンプレートは、hono コンテキストから html メソッドによってレンダリングされます。ここで重要な点は、ルート ハンドラーが cookieContext を受け取る asyncLocalStorage.run() メソッド内で実行されるということです。その結果、Cookie 関数を通じて DisplayCookies コンポーネントのこのコンテキストにアクセスできるようになります。
React サーバー コンポーネント内に Cookie を設定することはできないため、手動で行う必要があります:
ページを更新しましょう:
これで、Cookie が正常に取得され、表示されました。
結論
asyncLocalStorage には他にも多くの使用例があります。この機能を使用すると、ほぼすべてのサーバー フレームワークでカスタム コンテキストを構築できます。 asyncLocalStorage コンテキストは run() メソッドの実行内にカプセル化されるため、管理が容易になります。リクエストベースのシナリオを処理するのに最適です。 API はシンプルかつ柔軟で、状態ごとにインスタンスを作成することでスケーラビリティを実現します。認証、ロギング、機能フラグなどの個別のコンテキストをシームレスに維持できます。
その利点にもかかわらず、留意すべき考慮事項がいくつかあります。 asyncLocalStorage はコードに「魔法」を導入しすぎているという意見を聞いたことがあります。正直に言うと、この機能を初めて使用したとき、その概念を完全に理解するまでに時間がかかりました。もう 1 つ考慮すべき点は、コンテキストをモジュールにインポートすると、管理する必要がある新しい依存関係が作成されることです。ただし、最終的には、深くネストされた関数呼び出しを介して値を渡すことははるかに悪いことです。
読んでいただきありがとうございます。また次の投稿でお会いしましょう?
追記: ここで例 (プラス 1 つのボーナス) を見つけることができます
Bog Post ソース: https://www.aboutjs.dev/en/async-local-storage-is-here-to-help-you
以上が非同期ローカル ストレージが役に立ちますの詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。

JavaScript文字列置換法とFAQの詳細な説明 この記事では、javaScriptの文字列文字を置き換える2つの方法について説明します:内部JavaScriptコードとWebページの内部HTML。 JavaScriptコード内の文字列を交換します 最も直接的な方法は、置換()メソッドを使用することです。 str = str.replace( "find"、 "置換"); この方法は、最初の一致のみを置き換えます。すべての一致を置き換えるには、正規表現を使用して、グローバルフラグGを追加します。 str = str.replace(/fi

このチュートリアルでは、カスタムGoogle検索APIをブログまたはWebサイトに統合する方法を示し、標準のWordPressテーマ検索関数よりも洗練された検索エクスペリエンスを提供します。 驚くほど簡単です!検索をyに制限することができます

それで、あなたはここで、Ajaxと呼ばれるこのことについてすべてを学ぶ準備ができています。しかし、それは正確には何ですか? Ajaxという用語は、動的でインタラクティブなWebコンテンツを作成するために使用されるテクノロジーのゆるいグループ化を指します。 Ajaxという用語は、もともとJesse Jによって造られました

この記事シリーズは、2017年半ばに最新の情報と新鮮な例で書き直されました。 このJSONの例では、JSON形式を使用してファイルに単純な値を保存する方法について説明します。 キー価値ペア表記を使用して、あらゆる種類を保存できます

楽なWebページレイアウトのためにjQueryを活用する:8本質的なプラグイン jQueryは、Webページのレイアウトを大幅に簡素化します。 この記事では、プロセスを合理化する8つの強力なjQueryプラグイン、特に手動のウェブサイトの作成に役立ちます

コアポイント これは通常、メソッドを「所有」するオブジェクトを指しますが、関数がどのように呼び出されるかに依存します。 現在のオブジェクトがない場合、これはグローバルオブジェクトを指します。 Webブラウザでは、ウィンドウで表されます。 関数を呼び出すと、これはグローバルオブジェクトを維持しますが、オブジェクトコンストラクターまたはそのメソッドを呼び出すとき、これはオブジェクトのインスタンスを指します。 call()、apply()、bind()などのメソッドを使用して、このコンテキストを変更できます。これらのメソッドは、与えられたこの値とパラメーターを使用して関数を呼び出します。 JavaScriptは優れたプログラミング言語です。数年前、この文はそうでした

jQueryは素晴らしいJavaScriptフレームワークです。ただし、他のライブラリと同様に、何が起こっているのかを発見するためにフードの下に入る必要がある場合があります。おそらく、バグをトレースしているか、jQueryが特定のUIをどのように達成するかに興味があるからです

この投稿は、Android、BlackBerry、およびiPhoneアプリ開発用の有用なチートシート、リファレンスガイド、クイックレシピ、コードスニペットをコンパイルします。 開発者がいないべきではありません! タッチジェスチャーリファレンスガイド(PDF) Desigの貴重なリソース


ホットAIツール

Undresser.AI Undress
リアルなヌード写真を作成する AI 搭載アプリ

AI Clothes Remover
写真から衣服を削除するオンライン AI ツール。

Undress AI Tool
脱衣画像を無料で

Clothoff.io
AI衣類リムーバー

AI Hentai Generator
AIヘンタイを無料で生成します。

人気の記事

ホットツール

ドリームウィーバー CS6
ビジュアル Web 開発ツール

ゼンドスタジオ 13.0.1
強力な PHP 統合開発環境

EditPlus 中国語クラック版
サイズが小さく、構文の強調表示、コード プロンプト機能はサポートされていません

SublimeText3 英語版
推奨: Win バージョン、コードプロンプトをサポート!

ZendStudio 13.5.1 Mac
強力な PHP 統合開発環境
