JavaScriptにおけるPromiseの使い方と注意点について(推奨)

JavaScriptにおけるPromiseの使い方と注意点について(推奨)

1. 約束の説明

Promise は、非同期操作の最終状態 (失敗または正常完了) とその結果の値を表すために使用される JavaScript の標準組み込みオブジェクトです。これにより、非同期操作の最終的な成功または失敗の理由をレスポンス ハンドラーに関連付けることができます。つまり、promise を通じて、非同期操作の終了後に実行する操作をカスタマイズできます。この場合、非同期メソッドは同期メソッドと非常によく似ており、戻り値もありますが、この戻り値は最終値をすぐに返すのではなく、promise を返します。promise の状態が変化すると、対応するハンドラーがトリガーされます。

約束は常に次のいずれかの状態になります: 1. 保留中 2. 履行済み 3. 拒否済み

promise が最初に作成されたときは、保留状態です。これは、満たされても拒否されてもいません。これは、promise サポートにまだ追加されていない関数をラップするために使用されます。ラップされた関数は、非同期操作関数になります。操作が終了すると、次の図に示すように、1 つは満たされ、もう 1 つは拒否される 2 つの分岐が存在します。満たされたプロミスは後続の then メソッドを呼び出しますが、拒否されたプロミスは then メソッドを呼び出すか、catch メソッドによってキャッチされます。 then メソッドが 2 つの状態の Promise をキャプチャできるのはなぜですか?ここでは詳しくは触れませんが、以下で詳しく紹介します。

2. プロセスの方向性を約束する

上の図は Promise のフローチャートです。左から右に、Promise が保留状態にある場合、2 つの分岐を経てそれぞれ then メソッドまたは catch メソッドに入ることがわかります。これらの c メソッドは両方とも promise を返します。この Promise も確定し、その後に then メソッドまたは catch メソッドがある場合は、何もなくなるまで後続の then と catch に入ります。

つまり、promise と then または catch は非同期操作のチェーン構造を形成できます。js のイベント ループ メカニズムと組み合わせると、js の利点がより明確になります。これは、現在でもブラウザーでよく見られます。

プロセスの特性に注意を払う必要があります。

1. Promiseはオブジェクトです。その転送の成功は戻り値ではなく、状態の確定(成功または失敗)に依存します。

2. then と catch は関数です。Promise の状態が変化すると、その Promise に対応する then または catch メソッドが呼び出されます。これら 2 つのメソッド自体は Promise を返し、返された Promise はこれら 2 つのメソッドに続く then または catch メソッドに影響を与えます。両方のメソッドの戻り値は promise である必要があります。

3. 約束の創造

Promiseオブジェクトは、 newキーワードとそのコンストラクターによって作成されます。このコンストラクターは、エグゼキューター関数と呼ばれる関数をパラメーターとして受け取ります。この「ハンドラー関数」は、 resolverejectという 2 つの関数をパラメーターとして受け入れます。非同期タスクが正常に完了して結果値を返すと、 resolve関数が呼び出されます。非同期タスクが失敗して失敗の理由 (通常はエラー オブジェクト) を返すと、 reject関数が呼び出されます。次に例を示します。

myFirstPromise = new Promise(function(resolve, reject){
 //非同期コードが正常に実行されると、resolve(...) を呼び出し、非同期コードが失敗すると、reject(...) を呼び出します。
 // この例では、setTimeout(...) を使用して非同期コードをシミュレートします。実際のコードは、XHR リクエストまたは HTML5 API メソッドである可能性があります。
 setTimeout(関数(){
  resolve("Success!"); //コードは正常に実行されます。
 }, 250);
});

myFirstPromise.then(function(successMessage){
 // successMessage の値は、上記のresolve(...) メソッドを呼び出すことによって渡される値です。
 // successMessage パラメータは文字列型である必要はありません。これは単なる例です。 console.log("Yay! " + successMessage);
});

4. 約束の利点

promise が表示されない場合、非同期コード ブロックを呼び出すと、順序を維持する方法がありません。非同期コードの結果を順序どおりにする必要がある場合、どのように実現すればよいでしょうか。

従来は、非同期コードをレイヤーごとに埋め込んで順番に実装するのが一般的でしたが、これではコードのメンテナンスが難しくなり、開発の難易度が上がっていました。

doSomething(関数(結果) {
 doSomethingElse(結果、関数(newResult) {
 doThirdThing(newResult, 関数(finalResult) {
  console.log('最終結果が得られました: ' + finalResult);
 }, 失敗コールバック);
 }, 失敗コールバック);
}, 失敗コールバック);

これは典型的なコールバック地獄です。先ほど紹介したPromiseを使うと、コードはメンテナンスしやすいチェーン構造になる。

5. thenメソッドによって返されるpromise型

Promiseが満たされるか拒否されると、返された関数は非同期的に呼び出されます (現在のスレッド ループによってスケジュールされます)。具体的な戻り値は以下の規則に従って返されます。コールバック関数のthen

  • 値が返された場合、 thenまでに返された Promise が承認状態となり、返された値は承認状態のコールバック関数のパラメータ値として使用されます。
  • 値が返されない場合、 thenまでに返された Promise は承認済み状態となり、承認済み状態のコールバック関数のパラメータ値はundefined
  • エラーをスローすると、 thenによって返された Promise は拒否され、スローされたエラーは拒否コールバック関数のパラメータ値として使用されます。
  • すでに承認済み状態にある Promise を返すと、 thenに返された Promise も承認済み状態になり、その Promise の承認済み状態のコールバック関数のパラメータ値が、返された Promise の承認済み状態のコールバック関数のパラメータ値として使用されます。
  • すでに拒否された Promise が返された場合、 then返された Promise も拒否され、その Promise の拒否コールバック関数のパラメータ値が、返された Promise の拒否コールバック関数のパラメータ値として使用されます。
  • pending Promise を返すthen 、返される Promise の状態も保留中になり、最終状態は Promise の状態と同じになります。同時に、最終状態になったときに呼び出されるコールバック関数のパラメータは、Promise が最終状態になったときのコールバック関数のパラメータと同じになります。

6. catch で捕捉されたエラー

Catch は、Promise の組み合わせで発生するエラーをキャッチできますが、キャッチできないエラーが 2 種類あります。

1. 解決されたエラーはキャッチできない

//解決される新しい Promise を作成します var p1 = Promise.resolve("calling next");

var p2 = p1.catch(関数 (理由) {
 //このメソッドは呼び出されません console.log("catch p1!");
 console.log(理由);
});

p2.then(関数 (値) {
 console.log("次のプロミスは onFulfilled"); /* 次のプロミスは onFulfilled */
 console.log(value); /* 次を呼び出す */
}, 機能(理由){
 console.log("次のプロミスは onRejected");
 console.log(理由);
});

2. 非同期関数でスローされたエラーはキャッチできない

なお、筆者は個人的な実践を通じて、promise でラップされた非同期関数が正常に実行された後、resolve メソッドと reject メソッドを明示的に呼び出して、後続の then メソッドと catch メソッドをトリガーする必要があることを発見しました。promise メソッドが非同期関数ではなく通常の同期関数をラップしている場合、同期コードが正しく実行されないと、reject メソッドが呼び出されなくても、後続の catch メソッドでエラーを捕捉できます。ただし、同期コードにエラーがなく、resolve メソッドを明示的に呼び出して転送しない場合は、後続の then メソッドはトリガーされません。

7. 高度な例

<!DOCTYPE html>
<html lang="ja">
<ヘッド>
 <メタ文字セット="UTF-8">
 <meta name="viewport" content="width=デバイス幅、初期スケール=1.0">
 <title>ドキュメント</title>
 <スタイル>
  *{
   マージン: 10px;
  }
  html{
   幅: 100%;
   高さ: 100%;
  }
  体{
   幅: 100%;
   高さ: 100%;
   ディスプレイ:フレックス;
   アイテムの位置を中央揃えにします。
   コンテンツの中央揃え: 中央;
  }
  div.displaydatabox{
   幅: 300ピクセル;
   高さ: 300px;
   境界線の半径: 50px;
   テキスト配置: 中央;
   行の高さ: 300px;
   ボックスの影: 0 0 10px 2px 黒;
  }
  div.ボタン{
   幅: 100ピクセル;
   高さ: 50px;
   境界線の半径: 21px;
   境界線: 2px 実線オレンジ;
   行の高さ: 50px;
   テキスト配置: 中央;
   カーソル: ポインタ;
  }
 </スタイル>
</head>
<本文>
 <div class="button">作成</div>
 <div class="button">テキストを入力</div>
 <div class="button">消える</div>
 <script lang="javascript">
  buttonlist を document.querySelectorAll("div.button"); とします。
  本文を document.querySelector("本文") とします。
  ボタンリスト[0].onclick=関数()
  {
   div = document.createElement("div"); とします。
   div.className="ディスプレイデータボックス";
   body.appendChild(div);
  }
  ボタンリスト[2].onclick=関数()
  {
   div = document.querySelector("div.displaydatabox"); とします。
   body.removeChild(div);
  }
  ボタンリスト[1].onclick=関数(e)
  {
   p1 = new Promise((resolve, reject) => とします。
   {
    setTimeout(()=>{//setTimeout 関数を使用して非同期関数をシミュレートします。let div=document.querySelector("div.displaydatabox");
     div.textContent="これは Promise 実験です";
     //拒否(1);
     resolve(1); //resolveを呼び出すと最初に呼び出され、次に
    },2000);
   }).then(function(resolve){
    新しい Promise を返します ((resolve,reject)=>{
     console.log("これはステータスが確定していない Promise なので、後続の then メソッドは呼び出されません"); //resolve (1) //resolve または deny が呼び出されないため、ステータスは確定されません。呼び出されると 1 が出力され、ようやく呼び出されました!!
    })
   .then(関数(e){
    コンソールログ(e);
   });
   }).catch(関数(e)
   {
    console.log(e+"ブロックに入ることができません!!");
   }).then(()=>
   {
    console.log("ついに呼び出されました!!");
   })
  }
 </スクリプト>
</本文>
</html>

JavaScript における Promise の使い方と注意事項についてはこれで終わりです。JS における Promise の使い方に関するより関連性の高いコンテンツについては、123WORDPRESS.COM の過去の記事を検索するか、以下の関連記事を引き続き参照してください。今後とも 123WORDPRESS.COM をよろしくお願いいたします。

以下もご興味があるかもしれません:
  • JavaScript 非同期プログラミングにおける Promise の初期の使用法の詳細な説明
  • Node.js のコールバックを Promise に変換する方法
  • JS でカスタム Promise 操作の例を手書きする
  • node.js Promiseオブジェクトの使用例の分析
  • jsは再帰とpromiseを使用してデータを順番に要求します
  • Promise を使用して jsonp をカプセル化し、vue でデータを取得する
  • JS非同期プログラミングの深い理解 - Promise
  • JavaScript の async/await の原則と例の分析
  • JS スクリプトにおける async と defer の違いの詳細な説明
  • JSの非同期関数の意味と使用例のまとめ
  • Javascript非同期プログラミングの実装プロセスの詳細な説明async
  • JS で async/await を使用して非同期呼び出しを実装する方法
  • JS が async/await をジェネレータの構文糖と呼ぶ理由
  • JavaScript PromiseとAsync/Awaitの詳細な説明

<<:  node.js で Web サーバーを作成する手順の詳細な説明

>>:  uniAppエディタWeChatスライド問題について

推薦する

MySQL コード実行構造例の分析 [シーケンス、分岐、ループ構造]

この記事では、例を使用して MySQL コード実行構造について説明します。ご参考までに、詳細は以下の...

CSSレイアウトにおけるフローティング問題に対する4つの解決策の詳細な説明

1. 原因:サブボックスをフロートに設定した後の効果: 青いボックスをフロートに設定すると、標準のド...

mysql 5.7.5 m15 winx64.zip インストール チュートリアル

win7 64 ビットで mysql-5.7.5-m15-winx64 をインストールして構成する方...

WeChatアプレットリクエストの前処理方法の詳細な説明

質問一部のページでは、onload でデータを要求してからビューをレンダリングするため、ミニプログラ...

両端の CSS レイアウトのサンプルコード (親の負のマージンを使用)

最近、開発中に両端が揃ったレイアウトに遭遇しました。レイアウトはパーセンテージに基づいていました。以...

MySQL ベストプラクティス: パーティションテーブルの基本タイプ

MySQL パーティションテーブルの概要MySQL の人気が高まるにつれて、MySQL に保存される...

JS を使って 1 分で github+Jekyll ブログに訪問カウント機能を追加する実装

目次1分でgithub+Jekyllブログにトラフィック機能を追加する1. ジェクルとは何か1. J...

vue data が関数である理由をご存知ですか?

公式サイトの説明: コンポーネントを定義する場合、コンポーネントは複数のインスタンスを作成するために...

JavaScript を使用してページに動的な検証コードを実装する例

導入:現在、プログラム攻撃を防ぐために、ユーザーがログインまたは登録するときに多くの動的検証テクノロ...

MySQLで現在の時間間隔の前日のデータをクエリする

1. 背景実際のプロジェクトでは、分散スケジュールされたタスク実行の状況に遭遇することがあります。ス...

ElementUI el-select の過剰なデータに対する解決策についての簡単な説明

目次1. シナリオの説明2. 解決策オプションが多すぎる el-select コンポーネントの解決策...

ジョセフリング問題を解決する 3 つの JavaScript メソッド

目次概要問題の説明循環リンクリスト順序付き配列数学的再帰要約する概要ジョセフ・リング問題は、ジョセフ...

MySQLクエリ最適化プロセスを理解する

目次パーサーとプリプロセッサクエリオプティマイザーMySQL クエリの最適化には、解析、前処理、最適...

MySQL でスロークエリログを有効にする方法

1.1 はじめにスロークエリログを有効にすると、MySQL は指定された時間を超えるクエリステートメ...

MySQL Workbenchのダウンロードと使用方法のチュートリアルの詳細な説明

1. MySQL WorkbenchをダウンロードするWorkbench は、MySQL のグラフィ...