JavaScript の非同期プログラミングをステップごとに理解します。

青灯夜游
リリース: 2021-06-18 09:50:18
転載
1321 人が閲覧しました

この記事では、JavaScript での非同期プログラミングについて紹介します。一定の参考値があるので、困っている友達が参考になれば幸いです。

JavaScript の非同期プログラミングをステップごとに理解します。

非同期とは非同期を意味します....

このセクションは少し退屈かもしれませんが、JavaScript では非常に重要な概念であり、非常に重要です。役に立つので、学ぶ必要があります。

#目的

    開発効率を向上させ、保守しやすいコードを作成します

導入の質問

    リクエスト時にページが停止するのはなぜですか? ?
  • $.ajax({
      url: "www.xx.com/api",
      async: false, // true
      success: function(result) {
        console.log(result);
      },
    });
    ログイン後にコピー
    データは更新されるのに、DOM が更新されないのはなぜですか? ?
  • // 异步批量更新DOM(vue-nextTick)
    // <p id="app">{{num}}</p>
    new Vue({
      el: "#app",
      data: {
        num: 0,
      },
      mounted() {
        let dom = document.getElementById("app");
        while (this.num !== 100) {
          this.num++;
        }
        console.log("Vue num=" + this.num, "DOM num=" + dom.innerHTML);
        // Vue num=100,DOM num=0
        // nextTick or setTimeout
      },
    });
    ログイン後にコピー

非同期生成の理由

原因: シングル スレッド (1 つの時点で 1 つのことだけを行う)、ブラウザの JS エンジンがシングル スレッドである引き起こされた。

シングル スレッドとは、JS エンジンで IavaScript コードの解釈と実行を担当するスレッドが 1 つだけあることを意味します。これをメイン スレッドと呼ぶこともできます。

いわゆるシングル スレッドとは、一度に 1 つのタスクのみを完了できることを意味します。複数のタスクがある場合は、それらをキューに入れる必要があり、前のタスクが完了してから次のタスクが実行されます。

まずブラウザ カーネルのスレッド図を見てください。


JavaScript の非同期プログラミングをステップごとに理解します。

その中には、

レンダリング スレッドと JS スレッドがあります。 は相互に排他的です。

DOM ノードを変更と削除の 2 つの関数が同時に操作しているとします。複数のスレッドがある場合、2 つのスレッドが同時に実行されると、必ずデッドロックが発生します。そして問題も起こるだろう。

JS がシングルスレッドとして設計されるべき理由は、ブラウザーの特殊な環境のためです。

シングル スレッドの長所と短所:

このモードの利点は、実装が比較的簡単で、実行環境も比較的シンプルであることです。
欠点は、 1 つのタスクに時間がかかると、後続のタスクをキューに入れて待機する必要があり、プログラム全体の実行が遅れます。一般的なブラウザの応答不能 (サスペンドデス) は、特定の Javascript コードが長時間実行される (無限ループなど) ことが原因で発生することが多く、その結果、ページ全体がその場所でスタックし、他のタスクが実行できなくなります。
一般的な障害 (無限ループ):

while (true) {}
ログイン後にコピー

JS はもともとブラウザーで実行されるスクリプト言語として設計されていたため、それほど複雑にはしたくありませんでした。これは単一のスレッドになりました。つまり、

は一度に 1 つのことしか実行できません。

シングルスレッドブロッキングを解決するには

この欠点: 非同期が生成されます。 インスタント ラーメンを食べる例を挙げます。

同期: インスタント ラーメンを買う => 水を沸騰させる (見つめる) => 麺を調理する => インスタント ラーメンを食べる
  • 非同期 : インスタント ラーメンを買う => 水を沸騰させる (水が沸騰し、やかんが鳴る - コールバック) => テレビを見る => 麺を調理する (麺の準備ができてやかんが鳴る - コールバック) => テレビを見る => 時間が来たら電話する完了 => インスタント ラーメンを食べる
  • テレビを見ることは非同期操作であり、やかんの音はコールバック関数です。

非同期プログラミング

JS のコードの大部分は同期的に実行されます。非同期で実行される関数はほんのわずかです。非同期で実行されるコードには非同期プログラミングが必要です。

非同期コード

setTimeout(() => {
  console.log("log2");
}, 0);
console.log("log1");
// ?? log1 log2
ログイン後にコピー
非同期コードの特徴:

コードはすぐには実行されませんが、待機して将来の特定の時点で実行される必要があります。

# 同期コード <script>コードI/O 操作Timer (setTimeout, setInterval) レンダリング操作Promise(then)コールバック関数
#非同期コード
ネットワーク リクエスト (Ajax)
##async/await

非同期コードを記述する最も一般的な方法は、コールバック関数を使用することです。

HTTP ネットワーク リクエスト (リクエストは成功し、識別後に xx 操作が実行されます)

    DOM イベント バインディング メカニズム (ユーザーがイベントをトリガーした後に xx 操作が実行されます)
  • Timer (setTimeout, setInterval) (設定時間に達したら xx 操作を実行)
  • // 注意到click方法中是一个函数而不是一个变量
    // 它就是回调函数
    $("#btn_1").click(function() {
      alert("Btn 1 Clicked");
    });
    // 或者
    function click() {
      // 它就是回调函数
      alert("Btn 1 Clicked");
    }
    $("#btn_1").click(click);
    ログイン後にコピー
  • コールバック関数の欠点も明らかで、コールバック地獄を引き起こしやすいです。


JavaScript の非同期プログラミングをステップごとに理解します。非同期プログラミングの 3 つの方法

コールバック

    function getOneNews() {
      $.ajax({
        url: topicsUrl,
        success: function(res) {
          let id = res.data[0].id;
          $.ajax({
            url: topicOneUrl + id,
            success: function(ress) {
              console.log(ress);
              render(ress.data);
            },
          });
        },
      });
    }
    ログイン後にコピー
  • promise
    function getOneNews() {
      axios
        .get(topicsUrl)
        .then(function(response) {
          let id = response.data.data[0].id;
          return axios.get(topicOneUrl + id);
        })
        .then((res) => {
          render(res.data.data);
        })
        .catch(function(error) {
          console.log(error);
        });
    }
    ログイン後にコピー
  • async/await
    async function getOneNews() {
      let listData = await axios.get(topicsUrl);
      let id = listData.data.data[0].id;
      let data = await axios.get(topicOneUrl + id);
      render(data.data.data);
    }
    ログイン後にコピー
  • オンライン プレビュー

プレビュー アドレス: http:// jsrun.net/s43Kp/embedded/all/light

質問がありますか? ?

複数の非同期コードが同時に存在する場合、実行順序はどうなるでしょうか?どちらが先に実行され、どちらが後に実行されるのでしょうか?

マクロ タスクとマイクロ タスク

非同期コードの分割、非同期コードはマクロ タスクとマイクロ タスクに分けられます。

#マクロ タスク (急いでいない)##<script>全体のコードPromisesetTimeout/setInterval
マイクロ タスク (急いでいる)

事件循环(Event loop)

JavaScript の非同期プログラミングをステップごとに理解します。

执行顺序:

  • 执行整体代码<script>(宏任务)

  • 执行所有微任务

  • 执行一个宏任务

  • 执行渲染线程

  • 2->3->2->3...依次循环(在 2、3 步中又创建了新的宏、微任务)

重复从宏任务和微任务队列里拿出任务去执行。

总结

因为浏览器设计的原因,JS 线程和渲染线程互斥,所以 JS 线程被设计成了单线程。

因为单线程执行一些操作(如网络请求)时有堵塞的问题,所有产生了异步。

因为有了异步,所以产生了异步编程,从而有了回调函数。

因为回调函数写多了会产生回调地狱,所有又有了解决回调地狱的 Promise 写法

自 ES7 标准后有了比 Promise 更加优雅的写法 ———— async/await 写法,也是异步编程的最终解决方法。

因为 JS 的代码分为同步和异步代码,同步代码的执行顺序不必多说,自上而下的执行。

但是如果有多个异步的代码,他的执行顺序又是怎么的呢??

为了解决多个异步代码的执行顺序问了,有了事件循环(EventLoop),将异步任务区分为宏任务、微任务,依据规则依次执行。

至此 完!

练习

console.log("script start");
setTimeout(function() {
  console.log("timeout1");
}, 10);
new Promise((resolve) => {
  console.log("promise1");
  resolve();
  setTimeout(() => console.log("timeout2"), 10);
}).then(function() {
  console.log("then1");
});
console.log("script end");
ログイン後にコピー

写出 log 的输出结果,并说出理由。

更多编程相关知识,请访问:编程视频!!

以上がJavaScript の非同期プログラミングをステップごとに理解します。の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。

ソース:segmentfault.com
このウェブサイトの声明
この記事の内容はネチズンが自主的に寄稿したものであり、著作権は原著者に帰属します。このサイトは、それに相当する法的責任を負いません。盗作または侵害の疑いのあるコンテンツを見つけた場合は、admin@php.cn までご連絡ください。
最新の問題
人気のチュートリアル
詳細>
関連するチュートリアル
人気のおすすめ
最新のコース
最新のダウンロード
詳細>
ウェブエフェクト
公式サイト
サイト素材
フロントエンドテンプレート
私たちについて 免責事項 Sitemap
PHP中国語ウェブサイト:福祉オンライン PHP トレーニング,PHP 学習者の迅速な成長を支援します!