0
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 1 year has passed since last update.

ChatGPTと一緒にJavaScriptの非同期処理をマスターする

Last updated at Posted at 2023-05-15

Jacasciptの非同期処理をchatGPTで学んでみる。
JavaScriptの非同期処理にはいくつかの方法があるので、chatGPTに聞いてみた。

1. コールバック関数(Callback Functions):

コールバック関数は、非同期な操作が完了した後に呼び出される関数である。
典型的な例として、setTimeout関数がある。

console.log("処理開始");

setTimeout(function() {
  console.log("3秒経過しました");
}, 3000);

console.log("処理終了");

setTimeout関数によって、3秒後に指定されたコールバック関数(function(){・・・})が実行され、"3秒経過しました"と表示される。
setTimeout関数は非同期なので、"処理終了"が先に表示される。

2. Promise:

Promiseは非同期な操作の結果を表すオブジェクトである。非同期な処理が成功した場合にはresolve関数を呼び出し、失敗した場合にはreject関数を呼び出す。

console.log("処理開始");

const myPromise = new Promise(function(resolve, reject) {
  setTimeout(function() {
    resolve("3秒経過しました");
  }, 3000);
});

myPromise.then(function(result) {
  console.log(result);
  console.log("処理終了");
});

このコードでは、非同期な処理をPromiseで表現している。setTimeout関数が完了した後、resolve関数が呼び出され、その結果が.thenメソッドで取得され、表示されている。

コールバック関数よりもPromiseの方が柔軟で、ネストされたコードをフラットに表現することができる。また、複数の非同期処理を順番に実行したり、並行して実行したりすることもできる。

PromiseはJavaScriptの組み込みクラスとして実装されている。
その機能を理解するために、chatGPTに同じようなクラスを作ってもらう。

Promiseと同等のクラスの実装

以下にchatGPTに作ってもらった、Promiseと同じように機能するクラスMyPromiseの実装例を示す:

class MyPromise {
  constructor(executor) {
    // Promiseの状態
    this.state = 'pending';
    // Promiseが解決する値
    this.value = undefined;
    // Promiseが拒否された理由
    this.reason = undefined;
    // 成功時のコールバック関数の配列
    this.onResolvedCallbacks = [];
    // 失敗時のコールバック関数の配列
    this.onRejectedCallbacks = [];

    // 成功時の処理
    const resolve = (value) => {
      if (this.state === 'pending') {
        this.state = 'fulfilled';
        this.value = value;
        this.onResolvedCallbacks.forEach(fn => fn());
      }
    }

    // 失敗時の処理
    const reject = (reason) => {
      if (this.state === 'pending') {
        this.state = 'rejected';
        this.reason = reason;
        this.onRejectedCallbacks.forEach(fn => fn());
      }
    }

    try {
      // executorは即時実行される
      executor(resolve, reject);
    } catch (error) {
      // エラーが発生した場合は、Promiseを拒否する
      reject(error);
    }
  }

  then(onFulfilled, onRejected) {
    // 状態がfulfilledの場合、onFulfilledを実行する
    if (this.state === 'fulfilled') {
      onFulfilled(this.value);
    }
    // 状態がrejectedの場合、onRejectedを実行する
    if (this.state === 'rejected') {
      onRejected(this.reason);
    }
    // 状態がpendingの場合、コールバック関数を保存する
    if (this.state === 'pending') {
      this.onResolvedCallbacks.push(() => { onFulfilled(this.value) });
      this.onRejectedCallbacks.push(() => { onRejected(this.reason) });
    }
  }
}

このクラスは、Promiseのすべての機能を網羅しているわけではないが、Promiseの非同期処理の基本的な仕組みを理解するのに役立つ。

  1. コンストラクタ:
    MyPromiseというクラスのコンストラクタが定義されている。コンストラクタはexecutorという関数を受け取る。executor関数は、非同期な処理を実行し、成功時にはresolve関数を呼び出し、失敗時にはreject関数を呼び出す。

  2. Promiseの状態と値の管理:
    MyPromiseクラス内には、Promiseの状態(state)や解決する値(value)、拒否された理由(reason)を管理するための変数がある。初期状態では、stateはpending(保留中)に設定され、valueとreasonは未定義である。

  3. 成功時と失敗時の処理:

  • resolve関数は、Promiseが成功した場合に呼び出される。resolve関数は、stateをfulfilled(解決済み)に変更し、渡された値をvalueに設定する。また、成功時のコールバック関数(onResolvedCallbacks)を実行する。
  • reject関数は、Promiseが失敗した場合に呼び出される。reject関数は、stateをrejected(拒否済み)に変更し、渡された理由をreasonに設定する。また、失敗時のコールバック関数(onRejectedCallbacks)を実行する。
  1. thenメソッド:
    thenメソッドは、state(Promiseの状態)に応じて処理を行う。thenメソッドは、2つの引数、onFulfilled(成功時のコールバック関数)とonRejected(失敗時のコールバック関数)を受け取る。
  • もしstateがfulfilled(解決済み)であれば、onFulfilledを実行する。

  • もしstateがrejected(拒否済み)であれば、onRejectedを実行する。

  • もしstateがpending(保留中)であれば、"fulfilled"状態になったときに実行すべきコールバック関数、onFulfilledとonRejectedをコールバック関数の配列に保存する。
    つまり、Promiseの結果(解決値または拒否理由)がまだ利用できないときに、それらの結果が利用可能になったときに実行するためのコールバック関数を登録する。

MyPromiseクラスの使用例

以下は、MyPromiseクラスを使用した非同期処理の例である:

まず、指定した時間後に指定した値で解決するPromiseを生成する非同期処理を行うための関数waitFor()を作成する。

function waitFor(time, value) {
  return new MyPromise((resolve, reject) => {
    setTimeout(() => {
      resolve(value);
    }, time);
  });
}

次に、作成したwaitFor関数を使って、1秒後に'Hello, 'という文字列、その2秒後に'world!'という文字列を出力する。

waitFor(1000, 'Hello, ')
  .then(value => {
    console.log(value);
    return waitFor(2000, 'world!');
  })
  .then(value => {
    console.log(value);
  });

thenメソッドを使用すると、非同期処理が完了した後に行う処理を記述できる。
また、thenメソッドの中で新たにMyPromiseオブジェクトを返すと、そのMyPromiseオブジェクトの処理が終わるまで次のthenメソッドの処理は待機される。
このようにして非同期処理を順番に行うことができる。

3. async/await:

async/awaitを使うと、非同期な処理をより直感的に書ける。
非同期な関数の前にasyncキーワードを付け、非同期な処理の前にawaitキーワードを付けることで、処理の完了を待つことができる。
例:

console.log("処理開始");

async function myAsyncFunction() {
  await new Promise(function(resolve) {
    setTimeout(function() {
      resolve("3秒経過しました");
    }, 3000);
  });
}

async function main() {
  await myAsyncFunction();
  console.log("処理終了"); 
}

main();
  1. console.log("処理開始");:
    まず、"処理開始"というメッセージがコンソールに表示される。

  2. async function myAsyncFunction() { ... }:
    asyncを先頭につけることで、myAsyncFunction関数内で非同期処理を行うことを示している。

  3. new Promise(function(resolve) { ... });:
    新しいPromiseオブジェクトを作成している。このPromiseオブジェクトは、3秒後にresolve関数が呼び出されるまで保留状態(pending)となる。

  4. setTimeout(function() { ... }, 3000);:
    setTimeout関数を使用して非同期なタイマー処理を行っている。3秒後に指定されたコールバック関数resolve("3秒経過しました")が呼び出される。

  5. await new Promise(function(resolve) { ... });:
    awaitを使用して、非同期処理の完了を待っている。ここでは、Promiseオブジェクト(new Promise(function(resolve) { ... }))の解決を待っている。

  6. async function main() { ... }:
    asyncを先頭につけることで、main関数が非同期処理を行うことを示している。

  7. await myAsyncFunction();:
    awaitキーワードを使用して、myAsyncFunction関数の完了を待つ。ここでは、myAsyncFunctionが完了するまで次の行には進まないということを示している。

  8. console.log("処理終了");:
    myAsyncFunctionの処理がを完了した後に実行される。

結論

Javascriptの非同期処理を学びたくて、最初はchatGPTに「Promiseとは?」、「非同期処理を理解するための例を示して」などと聞いていたが、それだけでは理解するのが難しかった。

chatGPTから離れてw3schoolsというサイトのJavascriptのAsyncの章を読み、JavaScriptの非同期処理を理解することができた。Promiseの例題を見ていて、「Promiseはクラスではないのか?」と思い、ChatGPTに尋ねてみたところ、その通りだと回答があった。

そこで、chatGPTに「Promiseと同じように機能するクラスを実装してみて」と依頼してみた。
Promiseの例題とPromiseがどのように実装されているのかを学ぶことで、非同期処理がより理解しやすくなった。

ChatGPTに例題を作ってもらうだけでなく、機能の実装も教えてもらうことで、非同期処理やPromiseのような複雑な概念を理解するのがより簡単になった。

0
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?