日日操夜夜添-日日操影院-日日草夜夜操-日日干干-精品一区二区三区波多野结衣-精品一区二区三区高清免费不卡

公告:魔扣目錄網為廣大站長提供免費收錄網站服務,提交前請做好本站友鏈:【 網站目錄:http://www.ylptlb.cn 】, 免友鏈快審服務(50元/站),

點擊這里在線咨詢客服
新站提交
  • 網站:51998
  • 待審:31
  • 小程序:12
  • 文章:1030137
  • 會員:747

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

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

那么,在本文中我們將會通過實踐的方式讓你能更快速的理解它們的概念和用法,所以與許多傳統干巴巴的教程都不同,我們將通過以下四個示例開始:

  • 示例1:用生日解釋Promise的基礎知識
  • 示例2:一個猜數字的游戲
  • 示例3:從Web API中獲取國家信息
  • 示例4:從Web API中獲取一個國家的周邊國家列表

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

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

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

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的函數。

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的參數。

讓我們通過如下代碼來理解概念,相信通過這個例子你能了解Promise的基本概念。

如果Kayo沒有生病

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生病

onMyBirthday(true)
     .then((result) => {
          console.log(`I have ${result} cakes`); // 不執行
})
.catch((error) => {
     console.log(error); // 控制臺打印"我很難過"
})
.finally(() => {
     console.log("Party"); // 控制臺打印"Party"
});

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

基本需求:

  • 用戶可以輸入任意數字
  • 系統從1到6中隨機生成一個數字
  • 如果用戶輸入數字等于系統隨機數,則給用戶2分
  • 如果用戶輸入數字與系統隨機數相差1,給用戶1分,否則,給用戶0分
  • 用戶想玩多久就玩多久

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

const enterNumber = () => {
     return new Promise((resolve, reject) => {
          // 從這開始編碼
      });
};

我們要做的第一件事是向用戶索要一個數字,并在1到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函數,并拋出錯誤:

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分。

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,
});
}
});

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

const continueGame = () => {
return new Promise((resolve) => {
if (window.confirm("Do you want to continue?")) { // 向用戶詢問是否要繼續游戲
resolve(true);
} else {
resolve(false);
}
});
};

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

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

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就是可以把復雜難懂的異步代碼變成類同步語法的語法糖。

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

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方法。

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

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,我們可以很輕松的獲得數據,以下是代碼:

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 是代指該國家的國家代碼,以下是代碼

// 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來獲取中國的信息。

const fetchCountryAndNeighbors = async () => {
const china= await fetchCountry("cn");

console.log(china);
};

fetchCountryAndNeighbors();

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

20分鐘帶你掌握JS Promise和Async/Await

 

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

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

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

neighbors是一個Promise對象的數組。

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

const fetchCountryAndNeigbors = async () => {
const china = await fetchCountry("cn");

const neighbors = await Promise.all(
china.borders.map((border) => fetchCountry(border))
);

console.log(neighbors);
};

fetchCountryAndNeigbors();

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

20分鐘帶你掌握JS Promise和Async/Await

 

以下是示例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);
}
};

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在處理異步操作或不是同時發生的事情時很有用。相信在不斷的實踐中,對它的理解會越深、越強,希望這篇文章能對大家理解Promise和Async/Await帶來一些幫助。

這是本文中使用的代碼:Asdkjbasrksbr。

分享到:
標簽:JS Promise
用戶無頭像

網友整理

注冊時間:

網站:5 個   小程序:0 個  文章:12 篇

  • 51998

    網站

  • 12

    小程序

  • 1030137

    文章

  • 747

    會員

趕快注冊賬號,推廣您的網站吧!
最新入駐小程序

數獨大挑戰2018-06-03

數獨一種數學游戲,玩家需要根據9

答題星2018-06-03

您可以通過答題星輕松地創建試卷

全階人生考試2018-06-03

各種考試題,題庫,初中,高中,大學四六

運動步數有氧達人2018-06-03

記錄運動步數,積累氧氣值。還可偷

每日養生app2018-06-03

每日養生,天天健康

體育訓練成績評定2018-06-03

通用課目體育訓練成績評定