目次
予備知識
async の役割とは
await の役割とは
async/await の利点
async/await は誤解を招く可能性があります
async/await
太过串行化
错误处理
try…catch
让函数返回两个值
使用 .catch
结论
ホームページ ウェブフロントエンド jsチュートリアル JavaScriptでのasync/awaitの使い方を詳しく解説

JavaScriptでのasync/awaitの使い方を詳しく解説

Nov 19, 2020 pm 06:04 PM
javascript

ES8 で導入された

JavaScriptでのasync/awaitの使い方を詳しく解説

async/await は、JavaScript での非同期プログラミングにおける優れた改善です。これは、メインスレッドをブロックせずに、同期スタイルのコードを使用して resources に非同期的にアクセスする方法を提供します。ただし、落とし穴や問題もあります。この記事では、async/await をさまざまな観点から検討し、これらの兄弟を正しく効果的に使用する方法を示します。

予備知識

async の役割とは

MDN から確認できます:

async この関数は Promise オブジェクトを返します。 async 関数 (関数ステートメント、関数式、ラムダ式を含む) は、Promise オブジェクトを返します。return が関数内の直接量である場合、 async は、Promise.resolve() を通じて、この直接値を Promise オブジェクトにカプセル化します。

async 関数が値を返さない場合は、Promise.resolve(unknown) を返します。

await の役割とは

MDN から学んだこと:

await 私たちが待っているのは式です。この式の評価結果は、Promise オブジェクトまたはその他の値です (つまり、await は任意の式の結果を待つことができます)。

待機対象が Promise オブジェクトでない場合、await 式の結果が待機対象になります。

Promise オブジェクトを待機している場合、await はビジーになります。次のコードをブロックし、Promise オブジェクトが解決されるまで待機し、await 式の結果として解決された値を取得します。

これが、await を非同期関数で使用する必要がある理由です。非同期関数呼び出しはブロッキングを引き起こさず、その内部のすべてのブロッキングは Promise オブジェクトにカプセル化され、非同期に実行されます。

async/await の利点

async/await もたらされる最も重要な利点は、同期プログラミング スタイルです。例を見てみましょう:

// async/await
async getBooksByAuthorWithAwait(authorId) {
  const books = await bookModel.fetchAll();
  return books.filter(b => b.authorId === authorId);
}// promise
getBooksByAuthorWithPromise(authorId) {
  return bookModel.fetchAll()
    .then(books => books.filter(b => b.authorId === authorId));
}
ログイン後にコピー

明らかに、async/await バージョンは promise バージョンよりも理解しやすいです。 await キーワードを省略すると、コードは Python などの他の同期言​​語のようになります。

最も優れている点は、読みやすさだけではありません。 async/await 現在、すべての主要ブラウザは非同期機能を完全にサポートしています。

JavaScriptでのasync/awaitの使い方を詳しく解説

ネイティブ ブラウザのサポートにより、コードを切り替える必要がありません。さらに重要なのは、デバッグが容易になることです。関数のエントリ ポイントにブレークポイントを設定し、await 行をステップ オーバーすると、bookModel.fetchAll() がタスクを実行している間、デバッガがしばらく停止し、その後デバッガが停止するのがわかります。次の .filter 行に移動します。これは promise コードよりもはるかに単純です。promise では になければなりません。 .filter 行 に別のブレークポイントを設定します。

JavaScriptでのasync/awaitの使い方を詳しく解説

もう 1 つのあまり明らかではない利点は、async キーワードです。 asyncStatementgetBooksByAuthorWithAwait()関数の戻り値は promise であることが保証されているため、呼び出し元は getBooksByAuthorWithAwait を安全に使用できます。 () .then(...) または await getBooksByAuthorWithAwait()。次の例を考えてみましょう (悪い習慣です!):

getBooksByAuthorWithPromise(authorId) {
  if (!authorId) {
    return null;
  }
  return bookModel.fetchAll()
    .then(books => books.filter(b => b.authorId === authorId));
}
ログイン後にコピー

上記のコードでは、getBooksByAuthorWithPromisepromise (通常) または null 値を返す可能性があります。 (例外的な状況では) 例外的な状況では、呼び出し元は .then() を呼び出すことができません。 async ステートメントを使用すると、この状況は発生しません。

async/await は誤解を招く可能性があります

一部の記事では、async/waitPromise を比較し、これが次世代の JavaScript 非同期プログラミング スタイルであると主張しています。 、著者はこれに深く同意しません。 async/await は改善ですが、これは単なる糖衣構文であり、プログラミング スタイルを完全に変えるわけではありません。

本質的に、async 関数は依然として promise です。 async 関数を正しく使用するには、promise を理解する必要があります。さらに悪いことに、ほとんどの場合、promises async とともに を使用する必要があります。 ### 機能。

上記の例の

getBooksByAuthorWithAwait() 関数と getbooksbyauthorwithpromise() 関数を考えてみましょう。これらは機能的に同一であるだけでなく、インターフェースもまったく同じであることに注意してください!

これは、

getbooksbyauthorwithwait()promise を返すことを意味します。 #.then(...) を呼び出す方法としても使用されます。 <p>嗯,这未必是件坏事。只有 <code>await 的名字给人一种感觉,“哦,太好了,可以把异步函数转换成同步函数了”,这实际上是错误的。

async/await

那么在使用 async/await 时可能会犯什么错误呢?下面是一些常见的例子。

太过串行化

尽管 await 可以使代码看起来像是同步的,但实际它们仍然是异步的,必须小心避免太过串行化。

async getBooksAndAuthor(authorId) {
  const books = await bookModel.fetchAll();
  const author = await authorModel.fetch(authorId);
  return {
    author,
    books: books.filter(book => book.authorId === authorId),
  };
}
ログイン後にコピー

上述代码在逻辑上看似正确的,然而,这是错误的。

  1. await bookModel.fetchAll() 会等待 fetchAll() 直到 fetchAll() 返回结果。
  2. 然后 await authorModel.fetch(authorId) 被调用。

注意,authorModel.fetch(authorId) 并不依赖于 bookModel.fetchAll() 的结果,实际上它们可以并行调用!然而,用了 await,两个调用变成串行的,总的执行时间将比并行版本要长得多得多。

下面是正确的方式:

async getBooksAndAuthor(authorId) {
  const bookPromise = bookModel.fetchAll();
  const authorPromise = authorModel.fetch(authorId);
  const book = await bookPromise;
  const author = await authorPromise;
  return {
    author,
    books: books.filter(book => book.authorId === authorId),
  };
}
ログイン後にコピー

更糟糕的是,如果你想要一个接一个地获取项目列表,你必须依赖使用 promises:

async getAuthors(authorIds) {
  // WRONG, this will cause sequential calls
  // const authors = _.map(
  //   authorIds,
  //   id => await authorModel.fetch(id));// CORRECT
  const promises = _.map(authorIds, id => authorModel.fetch(id));
  const authors = await Promise.all(promises);
}
ログイン後にコピー

简而言之,你仍然需要将流程视为异步的,然后使用 await 写出同步的代码。在复杂的流程中,直接使用 promise 可能更方便。

错误处理

promise中,异步函数有两个可能的返回值: resolvedrejected。我们可以用 .then() 处理正常情况,用 .catch() 处理异常情况。然而,使用 async/await方式的,错误处理可能比较棘手。

try…catch

最标准的(也是作者推荐的)方法是使用 try...catch 语法。在 await 调用时,在调用 await 函数时,如果出现非正常状况就会抛出异常,await 命令后面的 promise 对象,运行结果可能是 rejected,所以最好把await 命令放在 try...catch 代码块中。如下例子:

class BookModel {
  fetchAll() {
    return new Promise((resolve, reject) => {
      window.setTimeout(() => { reject({&#39;error&#39;: 400}) }, 1000);
    });
  }
}// async/await
async getBooksByAuthorWithAwait(authorId) {
try {
  const books = await bookModel.fetchAll();
} catch (error) {
  console.log(error);    // { "error": 400 }
}
ログイン後にコピー

在捕捉到异常之后,有几种方法来处理它:

  • 处理异常,并返回一个正常值。(不在 catch 块中使用任何 return 语句相当于使用 return undefined,undefined 也是一个正常值。)
  • 如果你想让调用者处理它,你可以直接抛出普通的错误对象,如 throw errorr,它允许你在 promise 链中使用 async getBooksByAuthorWithAwait() 函数(也就是说,可以像getBooksByAuthorWithAwait().then(...).catch(error => ...) 处理错误); 或者可以用 Error 对象将错误封装起来,如 throw new Error(error),当这个错误在控制台中显示时,它将给出完整的堆栈跟踪信息。
  • 拒绝它,就像 return Promise.reject(error) ,这相当于 throw error,所以不建议这样做。

使用 try...catch 的好处:

  • 简单,传统。只要有Java或c++等其他语言的经验,理解这一点就不会有任何困难。
  • 如果不需要每步执行错误处理,你仍然可以在一个 try ... catch 块中包装多个 await 调用来处理一个地方的错误。

这种方法也有一个缺陷。由于 try...catch 会捕获代码块中的每个异常,所以通常不会被 promise 捕获的异常也会被捕获到。比如:

class BookModel {
  fetchAll() {
    cb();    // note `cb` is undefined and will result an exception
    return fetch(&#39;/books&#39;);
  }
}try {
  bookModel.fetchAll();
} catch(error) {
  console.log(error);  // This will print "cb is not defined"
}
ログイン後にコピー

运行此代码,你将得到一个错误 ReferenceError: cb is not defined。这个错误是由console.log()打印出来的的,而不是 JavaScript 本身。有时这可能是致命的:如果 BookModel 被包含在一系列函数调用中,其中一个调用者吞噬了错误,那么就很难找到这样一个未定义的错误。

让函数返回两个值

另一种错误处理方法是受到Go语言的启发。它允许异步函数返回错误和结果。详情请看这篇博客文章:

How to write async await without try-catch blocks in Javascript

简而言之,你可以像这样使用异步函数:

[err, user] = await to(UserModel.findById(1));
ログイン後にコピー

作者个人不喜欢这种方法,因为它将 Go 语言的风格带入到了 JavaScript 中,感觉不自然。但在某些情况下,这可能相当有用。

使用 .catch

这里介绍的最后一种方法就是继续使用 .catch()

回想一下 await 的功能:它将等待 promise 完成它的工作。值得注意的一点是 promise.catch() 也会返回一个 promise ,所以我们可以这样处理错误:

// books === undefined if error happens,
// since nothing returned in the catch statement
let books = await bookModel.fetchAll()
  .catch((error) => { console.log(error); });
ログイン後にコピー

这种方法有两个小问题:

  • 它是 promises 和 async 函数的混合体。你仍然需要理解 是promises  如何工作的。
  • 错误处理先于正常路径,这是不直观的。

结论

ES7引入的  async/await 关键字无疑是对J avaScrip t异步编程的改进。它可以使代码更容易阅读和调试。然而,为了正确地使用它们,必须完全理解 promise,因为 async/await 只不过是 promise 的语法糖,本质上仍然是 promise

英文原文地址:https://hackernoon.com/javascript-async-await-the-good-part-pitfalls-and-how-to-use-9b759ca21cda

更多编程相关知识,请访问:编程入门!!

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

このウェブサイトの声明
この記事の内容はネチズンが自主的に寄稿したものであり、著作権は原著者に帰属します。このサイトは、それに相当する法的責任を負いません。盗作または侵害の疑いのあるコンテンツを見つけた場合は、admin@php.cn までご連絡ください。

ホットAIツール

Undresser.AI Undress

Undresser.AI Undress

リアルなヌード写真を作成する AI 搭載アプリ

AI Clothes Remover

AI Clothes Remover

写真から衣服を削除するオンライン AI ツール。

Undress AI Tool

Undress AI Tool

脱衣画像を無料で

Clothoff.io

Clothoff.io

AI衣類リムーバー

AI Hentai Generator

AI Hentai Generator

AIヘンタイを無料で生成します。

ホットツール

メモ帳++7.3.1

メモ帳++7.3.1

使いやすく無料のコードエディター

SublimeText3 中国語版

SublimeText3 中国語版

中国語版、とても使いやすい

ゼンドスタジオ 13.0.1

ゼンドスタジオ 13.0.1

強力な PHP 統合開発環境

ドリームウィーバー CS6

ドリームウィーバー CS6

ビジュアル Web 開発ツール

SublimeText3 Mac版

SublimeText3 Mac版

神レベルのコード編集ソフト(SublimeText3)

WebSocket と JavaScript を使用してオンライン音声認識システムを実装する方法 WebSocket と JavaScript を使用してオンライン音声認識システムを実装する方法 Dec 17, 2023 pm 02:54 PM

WebSocket と JavaScript を使用してオンライン音声認識システムを実装する方法 はじめに: 技術の継続的な発展により、音声認識技術は人工知能の分野の重要な部分になりました。 WebSocket と JavaScript をベースとしたオンライン音声認識システムは、低遅延、リアルタイム、クロスプラットフォームという特徴があり、広く使用されるソリューションとなっています。この記事では、WebSocket と JavaScript を使用してオンライン音声認識システムを実装する方法を紹介します。

WebSocket と JavaScript: リアルタイム監視システムを実装するための主要テクノロジー WebSocket と JavaScript: リアルタイム監視システムを実装するための主要テクノロジー Dec 17, 2023 pm 05:30 PM

WebSocketとJavaScript:リアルタイム監視システムを実現するためのキーテクノロジー はじめに: インターネット技術の急速な発展に伴い、リアルタイム監視システムは様々な分野で広く利用されています。リアルタイム監視を実現するための重要なテクノロジーの 1 つは、WebSocket と JavaScript の組み合わせです。この記事では、リアルタイム監視システムにおける WebSocket と JavaScript のアプリケーションを紹介し、コード例を示し、その実装原理を詳しく説明します。 1.WebSocketテクノロジー

JavaScript と WebSocket を使用してリアルタイムのオンライン注文システムを実装する方法 JavaScript と WebSocket を使用してリアルタイムのオンライン注文システムを実装する方法 Dec 17, 2023 pm 12:09 PM

JavaScript と WebSocket を使用してリアルタイム オンライン注文システムを実装する方法の紹介: インターネットの普及とテクノロジーの進歩に伴い、ますます多くのレストランがオンライン注文サービスを提供し始めています。リアルタイムのオンライン注文システムを実装するには、JavaScript と WebSocket テクノロジを使用できます。 WebSocket は、TCP プロトコルをベースとした全二重通信プロトコルで、クライアントとサーバー間のリアルタイム双方向通信を実現します。リアルタイムオンラインオーダーシステムにおいて、ユーザーが料理を選択して注文するとき

WebSocketとJavaScriptを使ったオンライン予約システムの実装方法 WebSocketとJavaScriptを使ったオンライン予約システムの実装方法 Dec 17, 2023 am 09:39 AM

WebSocket と JavaScript を使用してオンライン予約システムを実装する方法 今日のデジタル時代では、ますます多くの企業やサービスがオンライン予約機能を提供する必要があります。効率的かつリアルタイムのオンライン予約システムを実装することが重要です。この記事では、WebSocket と JavaScript を使用してオンライン予約システムを実装する方法と、具体的なコード例を紹介します。 1. WebSocket とは何ですか? WebSocket は、単一の TCP 接続における全二重方式です。

JavaScript と WebSocket: 効率的なリアルタイム天気予報システムの構築 JavaScript と WebSocket: 効率的なリアルタイム天気予報システムの構築 Dec 17, 2023 pm 05:13 PM

JavaScript と WebSocket: 効率的なリアルタイム天気予報システムの構築 はじめに: 今日、天気予報の精度は日常生活と意思決定にとって非常に重要です。テクノロジーの発展に伴い、リアルタイムで気象データを取得することで、より正確で信頼性の高い天気予報を提供できるようになりました。この記事では、JavaScript と WebSocket テクノロジを使用して効率的なリアルタイム天気予報システムを構築する方法を学びます。この記事では、具体的なコード例を通じて実装プロセスを説明します。私たちは

簡単な JavaScript チュートリアル: HTTP ステータス コードを取得する方法 簡単な JavaScript チュートリアル: HTTP ステータス コードを取得する方法 Jan 05, 2024 pm 06:08 PM

JavaScript チュートリアル: HTTP ステータス コードを取得する方法、特定のコード例が必要です 序文: Web 開発では、サーバーとのデータ対話が頻繁に発生します。サーバーと通信するとき、多くの場合、返された HTTP ステータス コードを取得して操作が成功したかどうかを判断し、さまざまなステータス コードに基づいて対応する処理を実行する必要があります。この記事では、JavaScript を使用して HTTP ステータス コードを取得する方法を説明し、いくつかの実用的なコード例を示します。 XMLHttpRequestの使用

JavaScriptでinsertBeforeを使用する方法 JavaScriptでinsertBeforeを使用する方法 Nov 24, 2023 am 11:56 AM

使用法: JavaScript では、insertBefore() メソッドを使用して、DOM ツリーに新しいノードを挿入します。このメソッドには、挿入される新しいノードと参照ノード (つまり、新しいノードが挿入されるノード) の 2 つのパラメータが必要です。

JavaScript と WebSocket: 効率的なリアルタイム画像処理システムの構築 JavaScript と WebSocket: 効率的なリアルタイム画像処理システムの構築 Dec 17, 2023 am 08:41 AM

JavaScript は Web 開発で広く使用されているプログラミング言語であり、WebSocket はリアルタイム通信に使用されるネットワーク プロトコルです。 2 つの強力な機能を組み合わせることで、効率的なリアルタイム画像処理システムを構築できます。この記事では、JavaScript と WebSocket を使用してこのシステムを実装する方法と、具体的なコード例を紹介します。まず、リアルタイム画像処理システムの要件と目標を明確にする必要があります。リアルタイムの画像データを収集できるカメラ デバイスがあるとします。

See all articles