JavaScript/Typescript のシングルスレッドの性質: 非同期プログラミング

Jan 20 2023
最初の記事で、JS と TS の違いのいくつかについて書きました。ここで、単一スレッド言語としての非同期の性質を調べていきます。

最初の記事で、JS と TS の違いのいくつかについて書きました。

ここで、単一スレッド言語としての非同期の性質を調べていきます。

JavaScript と TypeScript では、シングルスレッドの性質により、一度に 1 つのタスクのみを実行できます。

一方、非同期プログラミングとは、タスクを非同期に実行する言語の機能を指し、他のタスクが完了するのを待っている間も実行のメインスレッドが実行を継続できるようにします。これは、コールバック、イベント、Promise 、およびasync / awaitを使用することで実現されます。

これらをコーディング用語で説明し始める前に、シングルスレッド言語の非同期タスクが、マルチタスクを実行しようとするときの私たちの脳とどのように非常によく似ているかについての非常に興味深い参考文献について話したいと思います。

このセクションでは、カイル・シンプソン氏の著書「You Dont Know Javascript」の中で、 Sequential Brainと非同期化の関係について書かれた長いテキスト/章を要約します。仕組みのコーディング部分のみに興味がある場合は、この部分をスキップしてください。

「ほとんどの人は、誰かがこう言うのを聞いたことがあると思います(自分自身でそう主張したことさえあります)、「私はマルチタスクです。 」しかし
、私たちはマルチタスクをする人なのでしょうか?私たちは本当に、同時に 2 つの意識的で意図的な行動を行い、その両方についてまったく同じ瞬間に考えたり推論したりすることができるのでしょうか? 私たちの最高レベルの脳機能では、並列マルチスレッド処理が行われているのでしょうか?

その答えは驚くかもしれませんが、おそらくそうではありません。

私たちの脳は実際にはそのように設定されていないようです。私たちは、多くの人が認めたいと思っているよりもはるかにシングルタスク型です。私たちが実際に考えることができるのは、特定の瞬間に 1 つのことだけです。

私は、心臓の鼓動、呼吸、まぶたのまばたきなど、無意識かつ潜在意識にある自動的な脳の機能すべてについて話しているのではありません。これらはすべて私たちの持続的な生活にとって重要なタスクですが、私たちは意図的にそれらに脳力を割り当てていません。」

シンプソン氏によれば、人間はコンピューターのように真の意味でマルチタスクを行うことができません。人間の脳が複数のタスクを同時に処理できることは事実ですが、すべてのタスクに同時に同じ注意を払うことはできません。代わりに、単一スレッドのプログラムが一度に 1 つのタスクしか実行できないのと同じように、タスク間で注意を素早く切り替えます。

ありがたいことに、私たちがソーシャル ネットワークのフィードを 3 分間で 15 回チェックすることに夢中になっている間、私たちの脳はバックグラウンド (スレッド!) でこれらすべての重要なタスクを実行しています。

友人や家族と電話で話しながら何かを入力しようとするなど、マルチタスクを装っているとき、私たちが実際に行っていることは、高速コンテキスト スイッチャーとして機能している可能性が最も高いです。言い換えれば、私たちは 2 つ以上のタスクを立て続けに行ったり来たりしながら、同時に各タスクを小さな単位で高速に進めます。私たちはそれを非常に速く行っているため、外の世界からは、これらのことを並行して行っているように見えます。

それは(JS で起こっていることと同じように)非同期イベント同時実行のように聞こえますか?!

私たちがさまざまなタスクを計画する方法と、私たちの脳が実際にそれらのタスクをどのように実行するかの間には、目に見える大きな違いがあります。
運用レベルでは私たちの脳は非同期イベントを発生しますが、私たちは連続した同期的な方法でタスクを計画しているようです。「店に行って、牛乳を買って、それからドライクリーニングに出さなければなりません。」

次のようなやるべき用事を計画する思考回路があることを実際に想像できますか?

「お店に行かなければいけないんですが (1)、でも途中できっと電話がかかってくると思います (2)。だから『こんにちは、ママ』って言って、彼女が話し始めている間、私は顔を上げます」 GPS でお店の住所 (3)を確認しましたが、読み込むのに 1 秒かかるので、お母さんの声がよく聞こえるようにラジオ (4) の音量を下げます
。その後、ジャケットを着るのを忘れたことに気づきます ( 5)外は寒いですが、大丈夫、運転を続けてママと話し続けてください…
そしてシートベルトの音が鳴り、シートベルトを締めることを思い出させてくれます (6)ので、「はい、ママ、私はシートベルトをしています、いつもそうしています!」。ああ、最後に:

GPS で道順が分かりました。今は…」

私たちが一日の計画を立て、何をどの順序で行うかを考える方法としてはばかげているように聞こえますが、それにもかかわらず、それはまさに私たちの脳が機能レベルでどのように動作するかです。ただし、これはマルチタスクではなく、単にコンテキストを高速に切り替えるだけであることに注意してください。

これを念頭に置いて、JavaScript での非同期プログラミングがどのように機能するかを詳しく見てみましょう。

ここでコーディングを始めます:

この記事の冒頭で述べたように、JavaScript/Typescript で非同期プログラミングを実行するには、Callbacks、Events、Promises、Async/Await の使用など、いくつかの方法があります。

  • コールバックは、別の関数に引数として渡され、外側の関数が完了した後に実行される関数です。例えば:
  • function greet(name, callback) {
      console.log(`Hello, ${name}!`);
      callback();
    }
    
    function sayGoodbye() {
      console.log("Goodbye!");
    }
    
    greet("John", sayGoodbye);
    // Output: "Hello, John!"
    // Output: "Goodbye!"
    

  • イベントは何かが起こったという信号であり、リスナーはそのイベントに応答して実行される関数です。例えば:
  • const button = document.querySelector("button");
    
    button.addEventListener("click", () => {
      console.log("Button was clicked!");
    });
    

  • Promiseは非同期操作の結果を表し、実際の Promise と同様に、解決 (成功) または拒否 (失敗) することができます。約束をするときは、それを守る(解決する)か、しないか(拒否する)かのどちらかです。
    Promise を使用すると、非同期操作を連鎖させるプロセスを簡素化できます。例えば:
  • const promise = new Promise((resolve, reject) => {
      setTimeout(() => {
        resolve("Completed Async Task");
      }, 1000);
    });
    
    promise.then((result) => {
      console.log(result);
    });
    // Output: "Async task completed" (after 1 second)
    

  • Async/await: async/await 構文を使用して、非同期コードを同期コードのように見せて動作させる JavaScript の機能。Async/await は Promise の上に構築されており、非同期コードの操作が容易になります。
  • async function greet(name) {
      return `Hello, ${name}!`;
    }
    
    async function main() {
      const greeting = await greet("John");
      console.log(greeting);
    }
    
    main();
    // Output: "Hello, John!"
    

全体として、非同期プログラミングでは、言語のシングルスレッドの性質を維持しながら、複数のタスクを実行できます。他のタスクが完了するのを待っている間もメインスレッドが実行を継続できるようにすることで、より応答性が高く効率的なプログラムが可能になります。

このコンテンツが気に入ったら、遠慮なくフォローしてください。他にもたくさんのプロジェクトが進行中であり、それについては近い将来書く予定です。それまで、

読んでくれてありがとう!