ホームページ  >  記事  >  ウェブフロントエンド  >  Javascript での async/await の仕組みの詳細な説明

Javascript での async/await の仕組みの詳細な説明

青灯夜游
青灯夜游転載
2021-01-13 18:46:161767ブラウズ

Javascript での async/await の仕組みの詳細な説明

関連する推奨事項: 「javascript ビデオ チュートリアル

async/await は ES7 の重要な機能の 1 つであり、現在、ES7 で優れていると認識されています。コミュニティの非同期ソリューション。現在、async/await の機能はすでに stage 3 の推奨事項となっています。TC39 の進捗状況をご覧ください。この記事では、async/await の仕組みについて説明します。この記事を読むことで、Promise、ジェネレーター、yield、その他の ES6 に関する関連知識が得られることを願っています。

async/await を詳しく紹介する前に、ES6 の現在の優れた非同期処理メソッドを確認してみましょう。次の例では、データ リクエストは Node.js のリクエスト モジュールを使用し、データ インターフェイスはサンプル デモンストレーションとして Github v3 api document によって提供されるリポジトリ コード リポジトリ詳細 API を使用します。

Promise による非同期の処理

Node.js の非同期 IO は、高い同時実行性を適切にサポートしますが、「コールバック」を悲惨なものにし、簡単にコールバック地獄を引き起こす可能性があります。名前付き関数の使用などの従来の方法では、ネスト レベルの数を減らし、コードをより明確に見せることができます。ただし、コーディングとデバッグのエクスペリエンスが低下し、名前付き関数の定義を見つけるために Ctrl F を頻繁に使用する必要があるため、IDE ウィンドウが頻繁に上下に移動します。 Promise を使用すると、ネスト レベルの数を大幅に減らすことができます。また、Promise の実装にはステート マシンが使用されており、関数内の解決と拒否によってプロセスが適切に制御され、一連のコード ロジックをシーケンシャル チェーンで実行できます。以下は Promise の使用例です:

const request = require('request');
// 请求的url和header
const options = {
  url: 'https://api.github.com/repos/cpselvis/zhihu-crawler',
  headers: {
    'User-Agent': 'request'
  }
};
// 获取仓库信息
const getRepoData = () => {
  return new Promise((resolve, reject) => {
    request(options, (err, res, body) => {
      if (err) {
        reject(err);
      }
      resolve(body);
    });
  });
};

getRepoData()
  .then((result) => console.log(result);)
  .catch((reason) => console.error(reason););

// 此处如果是多个Promise顺序执行的话,如下:
// 每个then里面去执行下一个promise
// getRepoData()
//   .then((value2) => {return promise2})
//   .then((value3) => {return promise3})
//   .then((x) => console.log(x))

ただし、Promise にはまだ欠陥があり、ネストを減らすだけで、ネストを完全に排除することはできません。たとえば、複数の Promise が連続して実行される場合、最初の Promise のロジックが実行された後、then 関数で 2 番目の Promise を実行する必要があります。これにより、ネストの層が作成されます。また、Promise を使用したコードはまだ非同期に見えますが、記述されたコードが同期になれば素晴らしいですね。

ジェネレーターによる非同期の処理

ジェネレーターに関しては、馴染みがないわけではありません。 Node.jsのコールバック処理では、私たちがよく使うTJ/Coをpromiseと組み合わせたジェネレーターを使って実装しています。Coはcoroutineの略で、などの言語のコルーチンから借用しています。パイソンとルア。非同期コード ロジックを同期的な方法で作成できるため、コードの読み取りと構成がより明確になり、デバッグが容易になります。

const co = require('co');
const request = require('request');

const options = {
  url: 'https://api.github.com/repos/cpselvis/zhihu-crawler',
  headers: {
    'User-Agent': 'request'
  }
};
// yield后面是一个生成器 generator
const getRepoData = function* () {
  return new Promise((resolve, reject) => {
    request(options, (err, res, body) => {
      if (err) {
        reject(err);
      }
      resolve(body);
    });
  });
};

co(function* () {
  const result = yield getRepoData;
  // ... 如果有多个异步流程,可以放在这里,比如
  // const r1 = yield getR1;
  // const r2 = yield getR2;
  // const r3 = yield getR3;
  // 每个yield相当于暂停,执行yield之后会等待它后面的generator返回值之后再执行后面其它的yield逻辑。
  return result;
}).then(function (value) {
  console.log(value);
}, function (err) {
  console.error(err.stack);
});

async/await 非同期の処理

co はコミュニティでは優れた非同期ソリューションですが、言語標準ではなく、単なる過渡的なソリューションです。 ES7 言語レベルでは、言語レベルの問題を解決するために async/await が提供されます。現在、IE Edge では async / await を直接使用できますが、Chrome と Node.js はまだサポートしていません。幸いなことに、babel はすでに非同期変換をサポートしているため、使用するときに babel を導入するだけで済みます。始める前に、次のパッケージを導入する必要があります。Preset-stage-3 には、必要な async/await コンパイル済みファイルが含まれています。

次のパッケージはブラウザ側と Node.js 側の両方にインストールする必要があります。

$ npm install babel-core --save
$ npm install babel-preset-es2015 --save
$ npm install babel-preset-stage-3 --save

babel が公式に提供する require フックメソッドを使用することをお勧めします。 require を介して入力すると、次のファイルは必要に応じて Babel によって処理されます。 CommonJs は同期モジュールの依存関係であることがわかっているため、これも実行可能な方法です。このとき、起動用のjsファイルと、実際にプログラムを実行するjsファイルの2つのファイルを記述する必要があります。

実際にプログラムを実行する開始ファイルindex.js

require('babel-core/register');
require('./async.js');

async.js

const request = require('request');

const options = {
  url: 'https://api.github.com/repos/cpselvis/zhihu-crawler',
  headers: {
    'User-Agent': 'request'
  }
};

const getRepoData = () => {
  return new Promise((resolve, reject) => {
    request(options, (err, res, body) => {
      if (err) {
        reject(err);
      }
      resolve(body);
    });
  });
};

async function asyncFun() {
 try {
    const value = await getRepoData();
    // ... 和上面的yield类似,如果有多个异步流程,可以放在这里,比如
    // const r1 = await getR1();
    // const r2 = await getR2();
    // const r3 = await getR3();
    // 每个await相当于暂停,执行await之后会等待它后面的
    //函数(不是generator)返回值之后再执行后面其它的await逻辑。
    return value;
  } catch (err) {
    console.log(err);
  }
}

asyncFun().then(x => console.log(`x: ${x}`)).catch(err => console.error(err));

注:

  • async は、パッケージ内部 コンテンツは同期的に実行でき、await は実行順序を制御します。await が実行されるたびに、プログラムは一時停止して await の戻り値を待ち、その後次の await を実行します。
  • await の後に呼び出される関数は Promise を返す必要があります。また、この関数はジェネレーターではなく通常の関数でもかまいません。
  • await は非同期関数でのみ使用できます。通常の関数で使用するとエラーが報告されます。
  • await コマンドの背後にある Promise オブジェクトは拒否される可能性があるため、await コマンドを try...catch コード ブロックに配置することをお勧めします。

実際、async/await の使用法は co の使用法と似ています。await と yield はどちらも一時停止を示し、内部のコードが一時停止できることを示すために async または co のレイヤーでラップされています。同期的に処理されます。ただし、async/await の後に続く await 関数は追加の処理を必要とせず、Co がジェネレーターとして記述する必要があります。

プログラミング関連の知識について詳しくは、プログラミング学習をご覧ください。 !

以上がJavascript での async/await の仕組みの詳細な説明の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。

声明:
この記事はcnblogs.comで複製されています。侵害がある場合は、admin@php.cn までご連絡ください。