概要一般的に、開発では、ネットワーク API 操作のクエリには時間がかかることが多く、応答を待つのに時間がかかる場合があります。そのため、要求されたときにプログラムが応答しない状況を回避するために、非同期プログラミングは開発者の基本的なスキルになります。 JavaScript で非同期操作を扱うとき、「Promise」という概念をよく耳にします。しかし、それがどのように機能し、どのように使用するかを理解するのは抽象的で難しい場合があります。 4つの例さて、この記事では、その概念と使用法をより早く理解できるように実用的な方法を使用します。そのため、多くの従来の無味乾燥なチュートリアルとは異なり、次の 4 つの例から始めます。
例1: 誕生日で説明する約束の基本まず、Promise の基本形式を見てみましょう。 Promise が実行されると、保留中 (実行中)、完了 (成功)、拒否 (失敗) の 3 つの状態に分けられます。 新しいPromise(function(resolve,reject) { if (/* 非同期操作が成功しました*/) { resolve(value); // Promiseの状態をパディングから実行済みに変更する } それ以外 { 拒否(エラー); // Promise の状態をパディングから拒否に変更します } }) 実装には3つのプロトタイプメソッドがあります: then、catch、finally 約束 .then((結果) => { //promise が受け入れられるか拒否されて実行が続行されます}) .catch((エラー) => { //promise は拒否されます}) .finally (() => { //promise が満たされると、とにかく実行されます}) 基本的な形式を紹介したので、次の例を見てみましょう。 ユーザーストーリー: 友人の Kayo が、2 週間後の私の誕生日パーティーでケーキを焼いてくれると約束してくれました。 すべてがうまくいって、カヨが病気でなければ、私たちはある程度の量のケーキを手に入れることができますが、カヨが病気であれば、ケーキはもらえません。しかし、ケーキがあってもなくても、私たちは誕生日パーティーをします。 この例では、上記の背景を JS コードに変換してみましょう。まず、Promise を返す関数を作成しましょう。 定数 onMyBirthday = (isKayoSick) => { 新しい Promise を返します ((resolve, reject) => { タイムアウトを設定する(() => { if (!isKayoSick) { 解決する(2); } それ以外 { 拒否(新しいエラー("悲しいです")); } }, 2000); }); }; JavaScript では、new Promise() を使用して新しい Promise を作成できます。これは、パラメータ (resolve, reject) => {} を持つ関数を受け入れます。 この関数では、resolve と deny はデフォルトで提供されるコールバック関数です。上記のコードを詳しく見てみましょう。 2000 ミリ秒後に onMyBirthday 関数を実行します。
ここで、onMyBirthday() は Promise を返すため、then、catch、finally メソッドにアクセスできるようになります。 then と catch で、先に resolve と reject に渡された引数にアクセスすることもできます。 次のコードを通して概念を理解しましょう 加代が病気でなかったら 私の誕生日(false) .then((結果) => { console.log(`I have ${result} cakes`); // コンソールに「I have 2 cakes」と表示される }) .catch((エラー) => { console.log(error); // 実行されませんでした}) .finally(() => { console.log("Party"); // コンソールに「Party」と表示される }); 加代が病気になったら 私の誕生日に(true) .then((結果) => { console.log(`I have ${result} cakes`); // 実行されませんでした}) .catch((エラー) => { console.log(error); // コンソールに「I'm sad」と表示される }) .finally(() => { console.log("Party"); // コンソールに「Party」と表示される }); この例を通して、Promise の基本的な概念を理解できると思います。 例2: 数字当てゲーム基本要件:
上記の要件を満たすために、まず enterNumber 関数を作成し、Promise を返します。 const 入力番号 = () => { 新しい Promise を返します ((resolve, reject) => { // ここからコーディングを開始します }); }; まず、ユーザーに数字を尋ね、1 から 6 までの数字をランダムに選択します。 const 入力番号 = () => { 新しい Promise を返します ((resolve, reject) => { const userNumber = Number(window.prompt("数字を入力してください (1 - 6):")); // ユーザーに数字を尋ねます const randomNumber = Math.floor(Math.random() * 6 + 1); // 1 から 6 までのランダムな数字を選択します }); }; ユーザーが数値以外の値を入力した場合。この場合、reject 関数を呼び出してエラーをスローします。 const 入力番号 = () => { 新しい Promise を返します ((resolve, reject) => { const userNumber = Number(window.prompt("数字を入力してください (1 - 6):")); // ユーザーに数字を尋ねます const randomNumber = Math.floor(Math.random() * 6 + 1); // 1 から 6 までのランダムな数字を選択します if (isNaN(userNumber)) { 拒否(new Error("入力タイプが正しくありません")); // ユーザーが入力した値が数値でない場合は例外がスローされ、拒否関数が呼び出されます} }); }; 次に、userNumber が RanomNumber と等しいかどうかを確認する必要があります。等しい場合は、ユーザーに 2 ポイントを与え、オブジェクト { points: 2, randomNumber } を渡して、resolve 関数を実行できます。 userNumber が randomNumber と 1 異なる場合、ユーザーに 1 ポイントが与えられます。それ以外の場合、ユーザーには 0 ポイントが与えられます。 新しい Promise を返します ((resolve, reject) => { const userNumber = Number(window.prompt("数字を入力してください (1 - 6):")); // ユーザーに数字を尋ねます const randomNumber = Math.floor(Math.random() * 6 + 1); // 1 から 6 までのランダムな数字を選択します if (isNaN(userNumber)) { 拒否(new Error("入力タイプが正しくありません")); // ユーザーが入力した値が数値でない場合は例外がスローされ、拒否関数が呼び出されます} if (ユーザー番号 === ランダム番号) { // 等しい場合は、ユーザーに 2 ポイントを与えます。resolve({ ポイント: 2, ランダム番号、 }); } それ以外の場合 ( ユーザー番号 === ランダム番号 - 1 || ユーザー番号 === ランダム番号 + 1 ){ // userNumber と randomNumber の差が 1 の場合、ユーザーに 1 ポイントを与えます。resolve({ ポイント: 1, ランダム番号、 }); } それ以外 { // それ以外の場合、ユーザーは 0 ポイントを獲得します。resolve({ ポイント: 0, ランダム番号、 }); } }); 次に、ユーザーにゲームを続行するかどうかを尋ねる別の関数を作成しましょう。 const 継続ゲーム = () => { 新しいPromise((resolve) => {を返す if (window.confirm("続行しますか?")) { // ユーザーにゲームを続行するかどうかを尋ねます。resolve(true); } それ以外 { 解決(偽); } }); }; ゲームが強制終了するのを防ぐために、作成した Promise では Reject コールバックを使用しません。 次に、推測ロジックを処理する関数を作成します。 const ハンドル推測 = () => { enterNumber() // Promiseオブジェクトを返します。then((result) => { alert(`Dice: ${result.randomNumber}: you got ${result.points} points`); // 解決が実行されると、ユーザーのスコアと乱数を取得します // ユーザーにゲームを続行するかどうかを尋ねます continueGame().then((result) => { if (結果) { handleGuess(); // はいの場合、ゲームは続行されます } else { alert("ゲーム終了"); // いいえの場合はゲーム終了ボックスを表示します} }); }) .catch((エラー) => alert(エラー)); }; handleGuess(); // handleGuess関数を実行する ここで、handleGuess 関数を呼び出すと、enterNumber() は Promise オブジェクトを返します。 Promise ステータスが解決された場合は、then メソッドを呼び出して推測結果とスコアをユーザーに通知し、ゲームを続行するかどうかをユーザーに尋ねます。 Promise ステータスが拒否された場合、入力が間違っていたというメッセージをユーザーに対して表示します。 しかし、このようなコードは問題を解決できますが、まだ読みにくいです。後で async/await を使用するように hanldeGuess をリファクタリングしましょう。 async/await については、すでにインターネット上に多くの説明があります。ここでは、シンプルかつ一般的な方法で説明したいと思います。async/await は、複雑で理解しにくい非同期コードを同期のような構文に変換できる構文糖です。 リファクタリングされたコードを見てみましょう。 const handleGuess = 非同期() => { 試す { const result = await enterNumber(); // then メソッドの代わりに、結果を直接取得するには promise の前に await を置く必要があります。alert(`Dice: ${result.randomNumber}: you got ${result.points} points`); const isContinuing = continueGame() を待機します。 継続中の場合 ハンドル推測(); } それ以外 { alert("ゲーム終了"); } } catch (error) { // catch メソッドは try、catch 関数 alert(error); に置き換えることができます。 } }; 関数の前に async キーワードを使用することで、非同期関数を作成します。関数内の使用方法は、次のように以前とは異なります。
参考までに、リファクタリング後の完全なコードを以下に示します。 const 入力番号 = () => { 新しい Promise を返します ((resolve, reject) => { const userNumber = Number(window.prompt("数字を入力してください (1 - 6):")); // ユーザーに数字を尋ねます const randomNumber = Math.floor(Math.random() * 6 + 1); // システムは 1 から 6 までの数字をランダムに選択します if (isNaN(userNumber)) { 拒否(new Error("入力タイプが間違っています")); // ユーザーが数字以外の数字を入力した場合、エラーが発生します} if (userNumber === randomNumber) { // ユーザーが数字を正しく推測した場合、ユーザーに2ポイントを与えます。resolve({ ポイント: 2, ランダム番号、 }); } それ以外の場合 ( ユーザー番号 === ランダム番号 - 1 || ユーザー番号 === ランダム番号 + 1 ) { // userNumber が randomNumber と 1 異なる場合、ユーザーに 1 ポイントを与えます。resolve({ ポイント: 1, ランダム番号、 }); } else { // 不正解、スコア0 解決({ ポイント: 0, ランダム番号、 }); } }); }; const 継続ゲーム = () => { 新しいPromise((resolve) => {を返す if (window.confirm("続行しますか?")) { // ユーザーにゲームを続行するかどうかを尋ねます。resolve(true); } それ以外 { 解決(偽); } }); }; const handleGuess = 非同期() => { 試す { const result = await enterNumber(); // await は then 関数を置き換えます alert(`Dice: ${result.randomNumber}: you got ${result.points} points`); const isContinuing = continueGame() を待機します。 継続中の場合 ハンドル推測(); } それ以外 { alert("ゲーム終了"); } } catch (error) { // catch メソッドは try、catch 関数 alert(error); に置き換えることができます。 } }; handleGuess(); // handleGuess関数を実行する 2 番目の例が完了したので、3 番目の例に進みましょう。 例3: Web APIから国情報を取得する多くの場合、API からデータを取得するときに、開発者は Promise を活用します。 https://restcountries.eu/rest/v2/alpha/cn を新しいウィンドウで開くと、国データが JSON 形式で表示されます。 Fetch API を使用すると、データを簡単に取得できます。コードは次のとおりです。 const fetchData = 非同期() => { const res = await fetch("https://restcountries.eu/rest/v2/alpha/cn"); // fetch() は Promise を返すので、それを待つ必要があります const country = await res.json(); // res は HTTP レスポンスのみなので、res.json() を呼び出す必要があります。 console.log(country); // 中国のデータは開発コンソールに記録されます }; フェッチデータ(); 必要な国のデータが揃ったので、最後のタスクに進みましょう。 例4: Web APIから国に隣接する国のリストを取得する次のfetchCountry関数は、例3のAPIから国情報を取得します。パラメータalpha3Codeは、国の国コードです。次のコードです。 // タスク 4: 中国の近隣諸国に関する情報を取得する const fetchCountry = async (alpha3Code) => { 試す { const res = フェッチを待つ( `https://restcountries.eu/rest/v2/alpha/${alpha3Code}` ); const データ = res.json() を待機します。 データを返します。 } キャッチ(エラー){ コンソール.log(エラー); } }; cn を alpha3code として渡して中国の情報を取得する fetchCountryAndNeighbors 関数を作成しましょう。 const fetchCountryAndNeighbors = 非同期 () => { const 中国 = fetchCountry("cn") を待機します。 console.log(中国); }; 国と近隣地域を取得します。 コンソールでオブジェクトの内容を確認します。 オブジェクトには、中国の近隣諸国の alpha3code のリストである border プロパティがあります。 さて、隣国の情報を次のように取得してみます。 const neighbors =china.borders.map((border) => fetchCountry(border)); neighbors は Promise オブジェクトの配列です。 Promise の配列を扱うときは、Promise.all を使用する必要があります。 const fetchCountryAndNeigbors = 非同期 () => { const 中国 = fetchCountry("cn") を待機します。 const neighbors = await Promise.all( china.borders.map((border) => fetchCountry(border)) ); console.log(近隣); }; 国と地域の情報をフェッチします。 コンソールでは、 Country オブジェクトのリストが表示されるはずです。 参考までに、例 4 のすべてのコードを次に示します。 const fetchCountry = async (alpha3Code) => { 試す { const res = フェッチを待つ( `https://restcountries.eu/rest/v2/alpha/${alpha3Code}` ); const データ = res.json() を待機します。 データを返します。 } キャッチ(エラー){ コンソール.log(エラー); } }; const fetchCountryAndNeigbors = 非同期 () => { const 中国 = fetchCountry("cn") を待機します。 const neighbors = await Promise.all( china.borders.map((border) => fetchCountry(border)) ); console.log(近隣); }; 国と地域の情報をフェッチします。 要約するこれら 4 つの例を実行すると、非同期操作、つまり同時に発生しない操作を処理するときに Promise が便利であることがわかります。継続的に練習することで、理解が深まり、強くなると信じています。この記事が Promise と Async/Await の理解に役立つことを願っています。 この記事で使用されているコードは次のとおりです: https://files.cnblogs.com/files/powertoolsteam/Promise-Async-Await-main.zip 以上がJavaScript PromiseとAsync/Awaitの詳しい説明です。JavaScript PromiseとAsync/Awaitについてさらに詳しく知りたい方は、123WORDPRESS.COMの関連記事もぜひご覧ください! 以下もご興味があるかもしれません:
|
<<: Linux で Nginx ロード バランシングを使用して複数の Tomcat を構成する方法
>>: MySQL5.6.17データベースをインストールするときにMy.iniファイルを構成する方法
序文Oracle や SQL Server などのデータベースには、ストレージ エンジンが 1 つだ...
序文セキュリティ上の理由から、会社が Linux サーバーへのすべてのログインにセキュリティ制限を課...
1. cmakeをインストールする1. cmakeの圧縮パッケージを解凍する [root@mysql...
目次既存のイメージからイメージを更新します。イメージを最初から構築する: Docker イメージ リ...
今日ご紹介したいのは、ネイティブ JS を使用してプログレス バーをドラッグし、要素の透明度を変更す...
グローバルオブジェクトすべてのモジュールは呼び出すことができますglobal: ブラウザの wind...
1. ネクサスサービス構築の意義イントラネットの統合プロキシとして、チームで共同開発する場合、全員が...
1. レンダリング2. 操作手順1. テンセントマップキーを申請する - 住所2. ミニプログラムの...
この記事では、バウンドボールゲームを実装するためのjQueryの具体的なコードを参考までに共有します...
準備: 192.168.16.128 192.168.16.129 2 台の仮想マシン。 Nginx...
コードをコピーコードは次のとおりです。 <前> <div> <sele...
序文:データベースの運用や保守の際には、リンクの総数がいくつあるか、アクティブなリンクがいくつあるか...
データベース MySQL バージョン 8.0.18 DBeaver.exeをダウンロードするダウンロ...
Linux 仮想マシン: VMware + Ubuntu 16.04.4 Windows ネイティブ...
ウィンドウ環境にmysql5.7.21をインストールします。詳細は次のとおりです。 1. MySQL...