中文字幕av专区_日韩电影在线播放_精品国产精品久久一区免费式_av在线免费观看网站

溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務條款》

如何理解JavaScript Promise

發布時間:2021-09-30 10:03:45 來源:億速云 閱讀:135 作者:柒染 欄目:編程語言

如何理解JavaScript Promise,針對這個問題,這篇文章詳細介紹了相對應的分析和解答,希望可以幫助更多想解決這個問題的小伙伴找到更簡單易行的方法。

一般在開發中,查詢網絡API操作時往往是比較耗時的,這意味著可能需要一段時間的等待才能獲得響應。因此,為了避免程序在請求時無響應的情況,異步編程就成為了開發人員的一項基本技能。

在JavaScript中處理異步操作時,通常我們經常會聽到 "Promise "這個概念。但要理解它的工作原理及使用方法可能會比較抽象和難以理解。

示例1:用生日解釋Promise基礎知識

首先,我們先來看看Promise的基本形態是什么樣的。

Promise執行時分三個狀態:pending(執行中)、fulfilled(成功)、rejected(失敗)。

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

new                   Promise(         function         (resolve, reject) {

             if                   (         /* 異步操作成功 */         ) {

                 resolve(value);          //將Promise的狀態由padding改為fulfilled

                     else                   {

                 reject(error);          //將Promise的狀態由padding改為rejected

             }

})

實現時有三個原型方法then、         catch         、finally

promise

.then((result) => {

             //promise被接收或拒絕繼續執行的情況

})

.         catch         ((error) => {

             //promise被拒絕的情況

})

.finally (() => {

             //promise完成時,無論如何都會執行的情況

})

基本形態介紹完成了,那么我們下面開始看看下面的示例吧。

用戶故事:我的朋友Kayo答應在兩周后在我的生日Party上為我做一個蛋糕。

如果一切順利且Kayo沒有生病的話,我們就會獲得一定數量的蛋糕,但如果Kayo生病了,我們就沒有蛋糕了。但不論有沒有蛋糕,我們仍然會開一個生日Party。

所以對于這個示例,我們將如上的背景故事翻譯成JS代碼,首先讓我們先創建一個返回Promise的函數。

1

2

3

4

5

6

7

8

9

10

11

const onMyBirthday = (isKayoSick) => {

           return                   new                   Promise((resolve, reject) => {

             setTimeout(() => {

               if                   (!isKayoSick) {

                 resolve(2);

                       else                   {

                 reject(         new                   Error(         "I am sad"         ));

               }

             }, 2000);

           });

};

在JavaScript中,我們可以使用new Promise()創建一個新的Promise,它接受一個參數為:(resolve,reject)=>{} 的函數。

在此函數中,resolve和reject是默認提供的回調函數。讓我們仔細看看上面的代碼。

當我們運行onMyBirthday函數2000ms后。

  • 如果Kayo沒有生病,那么我們就以2為參數執行resolve函數

  • 如果Kayo生病了,那么我們用new Error("I am sad")作為參數執行reject。盡管您可以將任何要拒絕的內容作為參數傳遞,但建議將其傳遞給Error對象。

現在,因為onMyBirthday()返回的是一個Promise,我們可以訪問then、catch和finally方法。我們還可以訪問早些時候在then和catch中使用傳遞給resolve和reject的參數。

讓我們通過如下代碼來理解概念

如果Kayo沒有生病

1

2

3

4

5

6

7

8

9

10

onMyBirthday(         false         )

           .then((result) => {

             console.log(`I have ${result} cakes`);          // 控制臺打印“I have 2 cakes” 

           })

           .         catch         ((error) => {

             console.log(error);          // 不執行

           })

           .finally(() => {

             console.log(         "Party"         );          // 控制臺打印“Party”

           });

如果Kayo生病

1

2

3

4

5

6

7

8

9

10

onMyBirthday(         true         )

           .then((result) => {

             console.log(`I have ${result} cakes`);          // 不執行

           })

           .         catch         ((error) => {

             console.log(error);          // 控制臺打印“我很難過”

           })

           .finally(() => {

             console.log(         "Party"         );          // 控制臺打印“Party”

           });

相信通過這個例子你能了解Promise的基本概念。

下面我們開始示例2

示例2:一個猜數字的游戲

基本需求:

  • 用戶可以輸入任意數字

  • 系統從1到6中隨機生成一個數字

  • 如果用戶輸入數字等于系統隨機數,則給用戶2分

  • 如果用戶輸入數字與系統隨機數相差1,給用戶1分,否則,給用戶0分

  • 用戶想玩多久就玩多久

對于上面的需求,我們首先創建一個enterNumber函數并返回一個Promise:

1

2

3

4

5

const enterNumber = () => {

           return                   new                   Promise((resolve, reject) => {

             // 從這開始編碼

           });

};

我們要做的第一件事是向用戶索要一個數字,并在1到6之間隨機選擇一個數字:

1

2

3

4

5

6

const enterNumber = () => {

           return                   new                   Promise((resolve, reject) => {

             const userNumber = Number(window.prompt(         "Enter a number (1 - 6):"         ));          // 向用戶索要一個數字

             const randomNumber = Math.floor(Math.random() * 6 + 1);          // 選擇一個從1到6的隨機數

           });

};

當用戶輸入一個不是數字的值。這種情況下,我們調用reject函數,并拋出錯誤:

1

2

3

4

5

6

7

8

9

10

const enterNumber = () => {

           return                   new                   Promise((resolve, reject) => {

             const userNumber = Number(window.prompt(         "Enter a number (1 - 6):"         ));          // 向用戶索要一個數字

             const randomNumber = Math.floor(Math.random() * 6 + 1);          //選擇一個從1到6的隨機數

 

             if                   (isNaN(userNumber)) {

               reject(         new                   Error(         "Wrong Input Type"         ));          // 當用戶輸入的值非數字,拋出異常并調用reject函數

             }

           });

};

下面,我們需要檢查userNumber是否等于RanomNumber,如果相等,我們給用戶2分,然后我們可以執行resolve函數來傳遞一個object { points: 2, randomNumber } 對象。

如果userNumber與randomNumber相差1,那么我們給用戶1分。否則,我們給用戶0分。

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

return                   new                   Promise((resolve, reject) => {

           const userNumber = Number(window.prompt(         "Enter a number (1 - 6):"         ));          // 向用戶索要一個數字

           const randomNumber = Math.floor(Math.random() * 6 + 1);          // 選擇一個從1到6的隨機數

 

           if                   (isNaN(userNumber)) {

             reject(         new                   Error(         "Wrong Input Type"         ));          // 當用戶輸入的值非數字,拋出異常并調用reject函數

           }

 

           if                   (userNumber === randomNumber) {

             // 如果相等,我們給用戶2分

             resolve({

               points: 2,

               randomNumber,

             });

                   else                   if                   (

             userNumber === randomNumber - 1 ||

             userNumber === randomNumber + 1

           ) {

             // 如果userNumber與randomNumber相差1,那么我們給用戶1分

             resolve({

               points: 1,

               randomNumber,

             });

                   else                   {

             // 否則用戶得0分

             resolve({

               points: 0,

               randomNumber,

             });

           }

});

下面,讓我們再創建一個函數來詢問用戶是否想繼續游戲:

1

2

3

4

5

6

7

8

9

const continueGame = () => {

           return                   new                   Promise((resolve) => {

             if                   (window.confirm(         "Do you want to continue?"         )) {          // 向用戶詢問是否要繼續游戲

               resolve(         true         );

                     else                   {

               resolve(         false         );

             }

           });

};

為了不使游戲強制結束,我們創建的Promise沒有使用Reject回調。

下面,我們創建一個函數來處理猜數字邏輯:

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

const handleGuess = () => {

           enterNumber()          // 返回一個Promise對象

             .then((result) => {

               alert(`Dice: ${result.randomNumber}: you got ${result.points} points`);          // 當resolve運行時,我們得到用戶得分和隨機數

       

               // 向用戶詢問是否要繼續游戲

               continueGame().then((result) => {

                 if                   (result) {

                   handleGuess();          // If yes, 游戲繼續

                         else                   {

                   alert(         "Game ends"         );          // If no, 彈出游戲結束框

                 }

               });

             })

             .         catch         ((error) => alert(error));

};

 

handleGuess();          // 執行handleGuess 函數

在這當我們調用handleGuess函數時,enterNumber()返回一個Promise對象。

如果Promise狀態為resolved,我們就調用then方法,向用戶告知競猜結果與得分,并向用戶詢問是否要繼續游戲。

如果Promise狀態為rejected,我們將顯示一條用戶輸入錯誤的信息。

不過,這樣的代碼雖然能解決問題,但讀起來還是有點困難。讓我們后面將使用async/await 對hanldeGuess進行重構。

網上對于 async/await 的解釋已經很多了,在這我想用一個簡單概括的說法來解釋:async/await就是可以把復雜難懂的異步代碼變成類同步語法的語法糖

下面開始看重構后代碼吧:

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

const handleGuess = async () => {

           try                   {

             const result = await enterNumber();          // 代替then方法,我們只需將await放在promise前,就可以直接獲得結果

 

             alert(`Dice: ${result.randomNumber}: you got ${result.points} points`);

 

             const isContinuing = await continueGame();

 

             if                   (isContinuing) {

               handleGuess();

                     else                   {

               alert(         "Game ends"         );

             }

                   catch                   (error) {          // catch 方法可以由try, catch函數來替代

             alert(error);

           }

};

通過在函數前使用async關鍵字,我們創建了一個異步函數,在函數內的使用方法較之前有如下不同:

  • 和then函數不同,我們只需將await關鍵字放在Promise前,就可以直接獲得結果。

  • 我們可以使用try, catch語法來代替promise中的catch方法。

下面是我們重構后的完整代碼,供參考:  

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

39

40

41

42

43

44

45

46

47

48

49

50

51

52

53

54

55

56

57

58

59

60

const enterNumber = () => {

           return                   new                   Promise((resolve, reject) => {

             const userNumber = Number(window.prompt(         "Enter a number (1 - 6):"         ));          // 向用戶索要一個數字

             const randomNumber = Math.floor(Math.random() * 6 + 1);          // 系統隨機選取一個1-6的數字

 

             if                   (isNaN(userNumber)) {

               reject(         new                   Error(         "Wrong Input Type"         ));          // 如果用戶輸入非數字拋出錯誤

             }

 

             if                   (userNumber === randomNumber) {          // 如果用戶猜數字正確,給用戶2分

               resolve({

                 points: 2,

                 randomNumber,

               });

                     else                   if                   (

               userNumber === randomNumber - 1 ||

               userNumber === randomNumber + 1

             ) {          // 如果userNumber與randomNumber相差1,那么我們給用戶1分

               resolve({

                 points: 1,

                 randomNumber,

               });

                     else                           // 不正確,得0分

               resolve({

                 points: 0,

                 randomNumber,

               });

             }

           });

};

 

const continueGame = () => {

           return                   new                   Promise((resolve) => {

             if                   (window.confirm(         "Do you want to continue?"         )) {          // 向用戶詢問是否要繼續游戲

               resolve(         true         );

                     else                   {

               resolve(         false         );

             }

           });

};

 

const handleGuess = async () => {

           try                   {

             const result = await enterNumber();          // await替代了then函數

 

             alert(`Dice: ${result.randomNumber}: you got ${result.points} points`);

 

             const isContinuing = await continueGame();

 

             if                   (isContinuing) {

               handleGuess();

                     else                   {

               alert(         "Game ends"         );

             }

                   catch                   (error) {          // catch 方法可以由try, catch函數來替代

             alert(error);

           }

};

 

handleGuess();          // 執行handleGuess 函數

我們已經完成了第二個示例,接下來讓我們開始看看第三個示例。

示例3:從Web API中獲取國家信息

一般當從API中獲取數據時,開發人員會精彩使用Promises。如果在新窗口打開https://restcountries.eu/rest/v2/alpha/cn,你會看到JSON格式的國家數據。

通過使用Fetch API,我們可以很輕松的獲得數據,以下是代碼:

1

2

3

4

5

6

7

8

9

const fetchData = async () => {

           const res = await fetch(         "https://restcountries.eu/rest/v2/alpha/cn"         ); // fetch() returns a promise, so we need to wait          for                   it

 

           const country = await res.json();          // res is now only an HTTP response, so we need to call res.json()

 

           console.log(country);          // China's data will be logged to the dev console

};

 

fetchData();

現在我們獲得了所需的國家/地區數據,讓我們轉到最后一項任務。

示例4:從Web API中獲取一個國家的周邊國家列表

下面的fetchCountry函數從示例3中的api獲得國家信息,其中的參數alpha3Code 是代指該國家的國家代碼,以下是代碼

1

2

3

4

5

6

7

8

9

10

11

12

13

14

// Task 4: 獲得中國周邊的鄰國信息

const fetchCountry = async (alpha3Code) => {

           try                   {

             const res = await fetch(

               `https:         //restcountries.eu/rest/v2/alpha/${alpha3Code}`

             );

 

             const data = await res.json();

 

             return                   data;

                   catch                   (error) {

             console.log(error);

           }

};

下面讓我們創建一個fetchCountryAndNeighbors函數,通過傳遞cn作為alpha3code來獲取中國的信息。

1

2

3

4

5

6

7

const fetchCountryAndNeighbors = async () => {

           const china= await fetchCountry(         "cn"         );

 

           console.log(china);

};

 

fetchCountryAndNeighbors();

在控制臺中,我們看看對象內容:  

如何理解JavaScript Promise

在對象中,有一個border屬性,它是中國周邊鄰國的alpha3codes列表。

現在,如果我們嘗試通過以下方式獲取鄰國信息。

1

2

const neighbors =

             china.borders.map((border) => fetchCountry(border));

neighbors是一個Promise對象的數組。

當處理一個數組的Promise時,我們需要使用Promise.all。

1

2

3

4

5

6

7

8

9

10

11

const fetchCountryAndNeigbors = async () => {

           const china = await fetchCountry(         "cn"         );

 

           const neighbors = await Promise.all(

             china.borders.map((border) => fetchCountry(border))

           );

 

           console.log(neighbors);

};

 

fetchCountryAndNeigbors();

在控制臺中,我們應該能夠看到國家/地區對象列表。

如何理解JavaScript Promise

以下是示例4的所有代碼,供您參考:

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

const fetchCountry = async (alpha3Code) => {

           try                   {

             const res = await fetch(

               `https:         //restcountries.eu/rest/v2/alpha/${alpha3Code}`

             );

             const data = await res.json();

             return                   data;

                   catch                   (error) {

             console.log(error);

           }

};

 

const fetchCountryAndNeigbors = async () => {

           const china = await fetchCountry(         "cn"         );

           const neighbors = await Promise.all(

             china.borders.map((border) => fetchCountry(border))

           );

           console.log(neighbors);

};

 

fetchCountryAndNeigbors();

完成這4個示例后,你可以看到Promise在處理異步操作或不是同時發生的事情時很有用。

關于如何理解JavaScript Promise問題的解答就分享到這里了,希望以上內容可以對大家有一定的幫助,如果你還有很多疑惑沒有解開,可以關注億速云行業資訊頻道了解更多相關知識。

向AI問一下細節

免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。

AI

武陟县| 琼海市| 青州市| 县级市| 湘西| 兴文县| 东兰县| 晋江市| 商都县| 紫阳县| 莒南县| 丹凤县| 徐汇区| 嘉鱼县| 泾源县| 平度市| 深圳市| 云南省| 铁岭县| 溧水县| 新建县| 长乐市| 福建省| 兴山县| 桃江县| 乐平市| 忻州市| 竹北市| 晋宁县| 兴仁县| 广昌县| 灵武市| 灌阳县| 日照市| 大埔区| 宣恩县| 新营市| 西乌珠穆沁旗| 阿拉善盟| 长阳| 北流市|