プログラム 技術

JavaScript/TypeScriptでの非同期処理について

今回はJavaScript/TypeScriptでの非同期処理についてになります。また、JavaScript/TypeScriptでは基本的にフレームワーク依存になってたりするため、フレームワークごとに記載していきます

名称バージョン
NodeJS10~
React16.8〜
Angular(RxJS)2〜
Vue.js2〜
NestJS6〜

JavaScriptとTypeScriptの違い

そもそもJavaScriptとTypeScriptって何が違うの?という話ですが、よく言われるのが型チェックとコンパイルチェックがあげられますが他にも以下があります

観点JavaScriptの場合TypeScriptの場合
型安全性なしあり(Promise など)
コンパイル時チェックなしasync/await の誤用を検出
IDE補完限定的充実(型情報に基づく)
エラーの型指定不可catch (e: unknown) で安全処理
ジェネリクス不可fetchJson() など汎用化可能
// TypeScript のみ可能な型安全な非同期処理
async function fetchJson<T>(url: string): Promise<T> {
  const res = await fetch(url);
  if (!res.ok) throw new Error(`HTTP error: ${res.status}`);
  return res.json() as Promise<T>;
}

// 使用時に型補完が効く
const user = await fetchJson<{ name: string; age: number }>("/api/user/1");
console.log(user.name); // ← 型補完あり

フレームワーク別非同期処理

以下それぞれのフレームワークごとの非同期処理となります

Node.js

まず初めに、NodeJSからになります。こちらは、NodeJSのバージョンごとに使用できるものが異なっているので注意が必要です
また、JavaScriptの標準仕様書、ECMAScript(ES)のバージョンが上がるごとにバージョンが古いWebアプリケーションだと動作しないことがあるので注意が必要となります

// Node.js 10以上: fs/promises(コールバックレス)
import { readFile } from "fs/promises"; // Node.js 14以上(ESM)
const data = await readFile("./data.txt", "utf-8");

// Node.js 16以上: 非同期ストリーム
for await (const chunk of readable) { console.log(chunk); }

// Top-level await(Node.js 16以上 + "type":"module")
const config = await readFile("./config.json", "utf-8");

React

次にフロントエンドとしてよく使用されているReactの非同期処理についてになります。useEffect + asyncはよく使われている方法だと思います

// React 16.8〜: useEffect + async(ES2017必須)
useEffect(() => {
  const load = async () => { // useEffect 直接 async 不可
    const data = await fetchData();
    setData(data);
  };
  load();
}, []);

// React 18〜: Suspense + React Query(ES2020推奨)
const { data, isLoading } = useQuery({
  queryKey: ["user"],
  queryFn: () => fetchJson<User>("/api/user"),
});

// React 19〜: use() フック(ES2020)
const data = use(fetchUserPromise); // Suspense と組み合わせ

Angular(RxJS)

もう一つフロントエンドとして使用されているAngularです。RxJS(Observable)が中心となります

// Angular 全バージョン: RxJS Observable(ES2015〜)
this.http.get<User>("/api/user/1").subscribe(user => {
  this.user = user;
});

// Angular 9〜: async pipe(テンプレートで非同期)
// user$ = this.userService.getUser(1); // Observable
// template: {{ user$ | async }}

// Angular 13〜: firstValueFrom(ES2020、Promise変換)
import { firstValueFrom } from "rxjs";
const user = await firstValueFrom(this.userService.getUser(1));

// Angular 17〜: Signals + toObservable(ES2022)
import { toObservable } from "@angular/core/rxjs-interop";
const userCount$ = toObservable(this.userSignal);

Vue.js

本ブログでは記事内で使用していないですが、Vue.jsは上記2つと同じフロントエンドとして使用されることがあります

// Vue 2: Options API(ES5〜)
export default {
  async created() {
    this.user = await fetchUser(1); // ES2017必要
  }
}

// Vue 3.0〜: Composition API + async setup(ES2015〜)
const { data } = await useFetch("/api/user"); // VueUse

// Vue 3.0〜: Pinia 非同期アクション(ES2017〜)
const store = defineStore("user", {
  actions: {
    async fetchUser(id: number) {
      this.user = await fetchJson<User>(`/api/user/${id}`);
    },
  },
});

// Vue 3.3〜: Suspense + async setup(ES2020)
// <Suspense> コンポーネントで async setup を待機

NestJS

こちらはこれまでと違いバックエンド向けとなっています

// NestJS 全バージョン: async/await + DI(ES2017〜)
@Controller("users")
export class UserController {
  constructor(private userService: UserService) {}

  @Get(":id")
  async getUser(@Param("id") id: string): Promise<User> {
    return this.userService.findOne(Number(id));
  }
}

// NestJS 8〜: Promise.allSettled(ES2020)
@Get()
async findAll() {
  const results = await Promise.allSettled([
    this.serviceA.fetch(),
    this.serviceB.fetch(),
  ]);
  return results.filter(r => r.status === "fulfilled");
}

最後に

最後になりますが、TypeScriptを使用する場合は以下のようにtsconfig.jsonを適宜編集する必要があるので注意が必要です

// tsconfig.json の target 設定目安
{
  "compilerOptions": {
    // React + Vite(ブラウザ向け)
    "target": "ES2020",
    "lib": ["ES2020", "DOM"],

    // NestJS 10(Node.js 16以上)
    "target": "ES2021",
    "lib": ["ES2021"],
    "module": "NodeNext",

    // NestJS 11(Node.js 18以上)
    "target": "ES2022",
    "lib": ["ES2022"],
    "module": "NodeNext",

    // Angular 17以上
    "target": "ES2022",
    "lib": ["ES2022", "DOM"]
  }
}

会社紹介

私が所属しているアドバンスド・ソリューション株式会社(以下、ADS)は一緒に働く仲間を募集しています

会社概要
「技術」×「知恵」=顧客課題の解決・新しい価値の創造

この方程式の実現はADSが大切にしている考えで、技術を磨き続けるgeekさと、顧客を思うloveがあってこそ実現できる世界観だと思っています
この『love & geek』の精神さえあれば、得意不得意はno problem!
技術はピカイチだけど顧客折衝はちょっと苦手。OKです。技術はまだ未熟だけど顧客と知恵を出し合って要件定義するのは大好き。OKです
凸凹な社員の集まり、色んなカラーや柄の個性が集まっているからこそ、常に新しいソリューションが生まれています

ミッション
私たちは、テクノロジーを活用し、業務や事業の生産性向上と企業進化を支援します

ホームページ
アドバンスド・ソリューション株式会社|ADS Co., Ltd.
アドバンスド・ソリューション株式会社|ADS Co., Ltd.

Microsoft 365/SharePoint/Power Platform/Azure による DX コンサル・シス ...

サイトへ移動

PR

-プログラム, 技術
-, , , , , ,