非同期 JS を理解する

王林
リリース: 2024-09-01 21:07:11
オリジナル
1019 人が閲覧しました

Understanding Async JS

Async JS の目標: バックグラウンドで実行される長時間実行タスクに対処すること

  • 使用例: AJAX 呼び出しを介してリモート サーバーからデータを取得します。
  • 例:画像、タイマー、プロミス、フェッチ API、Async-Await、Geolocation API、エラー処理のソースを設定します。

同期コード:

  • 実行コンテキストの一部である実行スレッドによって書き込まれた順序で 1 行ずつ実行されます。
  • Dis: AJAX 呼び出し、D/B アクセス、アラート ウィンドウなど、コードの 1 行の実行に時間がかかり、完了するまでコードの実行がブロックされる場合。

非同期コード

  • タイマーはコードをブロックせずにバックグラウンドで実行されます。つまり、実行のメインスレッドをブロックしません。
  • 非同期コードは、バックグラウンドで実行されるタスクが終了した後に実行されます。
  • 実行は、非同期タスクが作業を完了するのを待ちません。
  • 非同期 - 同時には発生しません。
  • コールバックによってコードが自動的に非同期になるわけではありません。元。配列マップ メソッドはコールバックを受け入れますが、コードは非同期になりません。タイマーなどの特定の関数のみが非同期で動作しますが、すべてのコールバックが非同期で動作するわけではありません。
const p = document.querySelector('.p');
setTimeout(function(){
  p.textContent = "Welcome to JS";
}, 3000); // C/b executes after duration.
p.style.color = 'red';
ログイン後にコピー
Ex. Setting source of an img is an async operation, while rest of the code is running. Once the image is loaded completely, a load event will be emitted by JS for which we can listen.

const img = document.querySelector('.cat');
img.src = 'cat.jpg'
img.addEventListener('load',function(){
  img.classList('fadeIn');
});
p.style.width = '300px';
ログイン後にコピー
  • イベント リスナーだけではコードが非同期になりません。たとえば、ボタンクリックリスナーはバックグラウンドで何も動作しません。したがって、非同期動作は関係しません。

アヤックス

  • 非同期でリモート Web サーバーと通信できるようになります。
  • データは、AJAX 呼び出しを使用して Web サーバーから動的に要求されます。

API

  • アプリ間の通信を可能にする別のソフトウェアで使用されるソフトウェア。
  • 例: DOM API、Geoloaction API などはすべて自己完結型のソフトウェアであり、ソフトウェアがそれらと対話できるようにします
  • クラスを使用し、いくつかのメソッドを公開することで API を実装できます。
  • オンライン API : サーバー上で実行され、データのリクエストを受信し、応答としてデータを送り返すアプリケーション。
  • API はバックエンド開発を使用して構築されるか、他の開発者によって無料で提供されるサードパーティ API を使用します。
  • 例:ほぼすべてのサンプル API があります。
  • 以前は XML が使用されていましたが、現在は JS オブジェクトを文字列に変換した JSON のみが使用されています。
# First API Call: Older way of doing AJAX using XHR. Modern way uses fetch API.
- CORS need to be Yes/Unknown to access 3rd party APIs from our code.
- AJAX call is done in the background, while the rest of the code keeps running which makes it non-blocking.
- Hence, register a callback for the load event on request object.
- Request is sent in the background, when its complete 'load' event will be fired. As soon data arrives, Callback fn will be called.

HTML:
<main class="container">
  <div class="countries">
</div>
</main>

JS:
const getCountryData = function(country){
const btn = document.querySelector('.btn-country');
const countriesContainer = document.querySelector('.countries');

// 1. request created
const request = new XMLHttpRequest(); 
// 2.request opened
request.open("GET", `https://restcountries.com/v3.1/name/${country}`); 
// 3. request sent
request.send();

// 4. When data arrives, load event will be fired & below C/b will be invoked.
// 5. response arrives in the property responseText of request object in JSON i.e big string of text will be received from AJAX call which needs to be converted to JS object.
// 6. Convert JSON to JS.
request.addEventListener("load", function () {
  // console.log(this);    this refers to request object here. 'this' can be replaced with request object.
  // console.log(this.responseText);  will only be set when data has arrived.

  // Both lines yield same result below.
  //const [ data ] = JSON.parse(this.responseText);
  const data = JSON.parse(this.responseText)[0];
  console.log(data);

  const html = `<article class="country">
  <img src=${data.flags.svg} alt="" class="country__img">
  <div class="country__data">
    <h3 class="country__name">${data.name.common}</h3>
    <h4 class="country__region">${data.region}</h4>
    <p class="country__row"><span>${(+data.population / 1000000).toFixed(1)}</span> mn</p>
    <p class="country__row"><span>${data.languages[Object.keys(data.languages)[0]]}</span></p>
    <p class="country__row"><span>${data.currencies[Object.keys(data.currencies)[0]].name}</span></p>
  </div>
</article>`;
  countriesContainer.insertAdjacentHTML('beforeend', html);
  countriesContainer.style.opacity = 1;
});
};

// All AJAX calls are happening in parallel
getCountryData('usa');
getCountryData('russia');
getCountryData('germany');
getCountryData('brazil');
getCountryData('india');

ログイン後にコピー

コールバック地獄:

  • AJAX リクエストを連鎖させると、順番に動作します。つまり、最初のリクエストが完了した後に 2 番目のリクエストが生成されます。

- 順番に実行する必要があるネストされた AJAX 呼び出しに対して定義されたネストされたコールバックが原因で発生します。

// This below triangular shape denotes callback hell. Makes code hard to maintain.
// GPP: Code which is hard to understand is bad code, hence difficult to add features
// Promises help us to resolve this Callback Hell problem.

setTimeout(() => {
  console.log("1 sec passed");
  setTimeout(() => {
    console.log("2 sec passed");
    setTimeout(() => {
      console.log("3 sec passed");
      setTimeout(() => {
        console.log("4 sec passed");
        setTimeout(() => {
          console.log("5 sec passed");
          }, 1000);
        }, 1000);
      }, 1000);
    }, 1000); 
}, 1000);



// Get the neighbouring countries
const renderCountry = function (data) {
  const btn = document.querySelector(".btn-country");
  const countriesContainer = document.querySelector(".countries");

  const html = `<article class="country">
  <img src=${data.flags.svg} alt="" class="country__img">
  <div class="country__data">
    <h3 class="country__name">${data.name.common}</h3>
    <h4 class="country__region">${data.region}</h4>
    <p class="country__row"><span>${(+data.population / 1000000).toFixed(
      1
    )}</span> mn</p>
    <p class="country__row"><span>${
      data.languages[Object.keys(data.languages)[0]]
    }</span></p>
    <p class="country__row"><span>${
      data.currencies[Object.keys(data.currencies)[0]].name
    }</span></p>
  </div>
</article>`;
  countriesContainer.insertAdjacentHTML("beforeend", html);
  countriesContainer.style.opacity = 1;
};

const getNeighbours = function (country) {
  const request = new XMLHttpRequest();
  request.open("GET", `https://restcountries.com/v3.1/name/${country}`);
  request.send();

  request.addEventListener("load", function () {
    const [data] = JSON.parse(this.responseText);
    console.log(data);
    renderCountry(data);

    const [neightbour] = data.borders;
    if(!neightbour) return;

    // request2 is Dependent on request1 as its invoke after request1. request2 will its own event listener.
    const request2 = new XMLHttpRequest();
    request2.open("GET", `https://restcountries.com/v3.1/alpha/${data.borders}`);
    request2.send();

    request2.addEventListener("load", function () {
    const [data2] = JSON.parse(this.responseText);
    console.log(data2);
    renderCountry(data2);
  });
};

getNeighbours("italy");

ログイン後にコピー

以上が非同期 JS を理解するの詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。

ソース:dev.to
このウェブサイトの声明
この記事の内容はネチズンが自主的に寄稿したものであり、著作権は原著者に帰属します。このサイトは、それに相当する法的責任を負いません。盗作または侵害の疑いのあるコンテンツを見つけた場合は、admin@php.cn までご連絡ください。
人気のチュートリアル
詳細>
最新のダウンロード
詳細>
ウェブエフェクト
公式サイト
サイト素材
フロントエンドテンプレート