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スライド問題について

推薦する

Nginxの現在の制限設定の詳細な説明

この記事では、最も単純なものから最も複雑なものまで、Nginx の現在の制限構成を例を使って説明しま...

JavaScriptはパスワードボックスの検証情報を実装します

この記事では、パスワードボックスの検証情報を実装するためのJavaScriptの具体的なコードを例と...

美容・スタイリングウェブサイト向けのカラーマッチングテクニックと効果表示

色はあらゆるウェブサイトにとって最も重要な要素の 1 つであり、閲覧者に大きな影響を与えるため、色の...

Dockerは指定されたメモリで操作を実行します

次のように: -m, --memory メモリ制限。形式は数値と単位です。単位は b、k、m、g の...

エラー 2002 (HY000): ソケット '/tmp/mysql.sock' 経由でローカル MySQL サーバーに接続できません

エラーメッセージ:エラー 2002 (HY000): ソケット '/tmp/mysql.so...

uniapp アプレットでウォーターフォール フロー レイアウトを実装するためのアイデアとコード

1. はじめに今、ウォーターフォールフローについて書くことは、古い内容の焼き直しと見なされますか?気...

MySQL 5.7.27 のインストールと設定方法のグラフィックチュートリアル

MySQL 5.7.27のインストールチュートリアルは以下のように記録され、皆さんと共有されています...

MySQLがクエリキャッシュをキャンセルした理由

MySQL には以前、クエリ キャッシュ (Query Cache) がありました。8.0 以降では...

JS 矢印関数に適さないシナリオは何ですか?

目次概要オブジェクトにメソッドを定義するオブジェクトリテラルオブジェクトプロトタイプ動的コンテキスト...

Vue+Bootstrapでシンプルな学生管理システムを実現

参考までに、vueとbootstrapを使って比較的シンプルな生徒管理システムを作りました。具体的な...

MySQLデータベースのマスタースレーブレプリケーションの長い遅延に対する解決策

序文MySQL マスター スレーブ レプリケーションの遅延は、業界では長年の問題となっています。遅延...

MySQLで重複行を削除する方法

SQL文 /* MySQL で重複行を削除するいくつかの方法 ---Chu Minfei ---20...

Mysqlのインポートとエクスポート時に発生する問題の解決

背景すべての業務を Docker の運用管理に移行してから、一連の落とし穴に遭遇しましたが、今回は ...

CSSで検索ボックスを非表示にする機能を実装します(アニメーション順方向と逆方向のシーケンス)

上部のメニュー バーに検索ボックスを配置するのは一般的なシナリオですが、検索機能がそれほど頻繁に使用...

Linux で MySQL のスケジュールバックアップを実装する方法

実際のプロジェクトでは、緊急事態を防ぐためにデータベースを頻繁にバックアップする必要があります。しば...