Im Allgemeinen ist das Abfragen von Netzwerk-API-Vorgängen in der Entwicklung oft zeitaufwändig, was bedeutet, dass es eine Weile dauern kann, bis man eine Antwort erhält. Um zu vermeiden, dass das Programm auf Anfrage nicht mehr reagiert, ist die asynchrone Programmierung daher zu einer Grundkompetenz für Entwickler geworden.
Beim Umgang mit asynchronen Vorgängen in JavaScript hören wir normalerweise den Begriff „Promise“. Aber zu verstehen, wie es funktioniert und wie man es nutzt, kann abstrakt und schwer zu verstehen sein.
Verwandte Empfehlungen: „Javascript-Video-Tutorial“
In diesem Artikel werden wir praktische Methoden verwenden, um Ihnen zu helfen, ihre Konzepte und Verwendung schneller zu verstehen, sodass sie sich von vielen herkömmlichen trockenen Tutorials unterscheiden. Wir beginnen mit die folgenden vier Beispiele:
Werfen wir zunächst einen Blick auf die Grundform von Promise.
Versprechen wird bei der Ausführung in drei Zustände unterteilt: ausstehend (wird ausgeführt), erfüllt (erfolgreich) und abgelehnt (fehlgeschlagen).
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完成时,无论如何都会执行的情况 })
Die Einführung in die Grundform ist abgeschlossen, also schauen wir uns zunächst die folgenden Beispiele an.
Benutzergeschichte: Mein Freund Kayo hat versprochen, mir in zwei Wochen einen Kuchen für meine Geburtstagsfeier zu backen.
Wenn alles gut geht und Kayo nicht krank wird, bekommen wir eine bestimmte Menge Kuchen, aber wenn Kayo krank wird, bekommen wir keinen Kuchen. Aber ob mit oder ohne Kuchen, wir werden trotzdem eine Geburtstagsfeier veranstalten.
Für dieses Beispiel übersetzen wir also die obige Hintergrundgeschichte in JS-Code. Erstellen wir zunächst eine Funktion, die ein Versprechen zurückgibt.
const onMyBirthday = (isKayoSick) => { return new Promise((resolve, reject) => { setTimeout(() => { if (!isKayoSick) { resolve(2); } else { reject(new Error("I am sad")); } }, 2000); }); };
In JavaScript können wir new Promise() verwenden, um ein neues Promise zu erstellen, das eine Funktion mit den Parametern akzeptiert: (auflösen, abweisen)=>{}.
In dieser Funktion sind Auflösen und Ablehnen die standardmäßig bereitgestellten Rückruffunktionen. Schauen wir uns den obigen Code genauer an.
Wenn wir die Funktion onMyBirthday 2000 ms später ausführen.
Da onMyBirthday() nun ein Promise zurückgibt, haben wir Zugriff auf die Methoden then, Catch und Finally. Wir haben auch Zugriff auf die Parameter, die früher zum Auflösen und Zurückweisen übergeben wurden, und können sie verwenden.
Lassen Sie uns das Konzept anhand des folgenden Codes verstehen
Wenn Kayo nicht krank ist
onMyBirthday(false) .then((result) => { console.log(`I have ${result} cakes`); // 控制台打印“I have 2 cakes” }) .catch((error) => { console.log(error); // 不执行 }) .finally(() => { console.log("Party"); // 控制台打印“Party” });
Wenn Kayo krank ist
onMyBirthday(true) .then((result) => { console.log(`I have ${result} cakes`); // 不执行 }) .catch((error) => { console.log(error); // 控制台打印“我很难过” }) .finally(() => { console.log("Party"); // 控制台打印“Party” });
Ich glaube, Sie können das Grundkonzept von Promise anhand dieses Beispiels verstehen. Wir beginnen mit Beispiel 2 eine Zahl Wenn sie gleich der Zufallszahl des Systems ist, erhält der Benutzer 2 Punkte erhält 0 Punkte
Der Benutzer kann so lange spielen, wie er möchte
const enterNumber = () => { return new Promise((resolve, 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的随机数 }); };
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函数 } }); };
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); } }); };
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关键字,我们创建了一个异步函数,在函数内的使用方法较之前有如下不同:
下面是我们重构后的完整代码,供参考:
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 函数
我们已经完成了第二个示例,接下来让我们开始看看第三个示例。
一般当从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();
现在我们获得了所需的国家/地区数据,让我们转到最后一项任务。
下面的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();
在控制台中,我们看看对象内容:
在对象中,有一个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();
在控制台中,我们应该能够看到国家/地区对象列表。
以下是示例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带来一些帮助。
以下是本文中使用的代码:
https://files.cnblogs.com/files/powertoolsteam/Promise-Async-Await-main.zip
原文出处:https://www.freecodecamp.org/news/learn-promise-async-await-in-20-minutes/
更多编程相关知识,请访问:编程视频!!
Das obige ist der detaillierte Inhalt vonLernen Sie schnell Promise und Async/Await in JavaScript. Für weitere Informationen folgen Sie bitte anderen verwandten Artikeln auf der PHP chinesischen Website!