范文健康探索娱乐情感热点
投稿投诉
热点动态
科技财经
情感日志
励志美文
娱乐时尚
游戏搞笑
探索旅游
历史星座
健康养生
美丽育儿
范文作文
教案论文

20分钟带你掌握JSPromise和AsyncAwait

  一般在开发中,查询网络 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、finallypromise .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();
  在控制台中,我们看看对象内容:
  在对象中,有一个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带来一些帮助。
  这是本文中使用的代码:Asdkjbasrksbr。

二人世界新玩法!4K高清画质,沉浸式氛围,90后新婚巴适现在越来越多的90后新生家庭都有自己的想法,打造一个多功能的智慧家庭,成为年轻新婚一族的向往。激光电视作为新兴的科技潮品,慢慢走进年轻人的视野。在家里也能享受到影院级4K画质的沉浸用了环保建材,甲醛就不会超标吗?你以为自己用了高端环保建材,新房装修后甲醛就不会超标吗?听完我的分析再下结论。选购建材的时候,你会发现,各大品牌都会标明甲醛达标,那是啊,不达标就不能卖了嘛那这些建材真的达标吗??我们到底需要什么样的居家环境?原来是有标准可以量化的我们总是说要高品质的居家环境,可是有个特别拷问灵魂的问题到底高品质的居家环境是啥样的?有没有一个可以量化可衡量的标准?感官标准从感觉上来判断,现代家庭舒适环境标准,起码要达到五恒,恒洁与网易家居携手推出质美中国一起探寻未来人居更多可能随着科技的不断进步,以及社会的不断发展,智能生活开始被越来越多的人所接受,人们对其的需求也越来越大。为了更好的探索智能与设计,探寻未来人居的更多可能,恒洁与网易家居携手推出了质美中独爱这份可爱,我的爱车比亚迪E1比亚迪E1一经面世,就凭借其可爱小巧的车身,及非凡的产品力,获得了不少消费者的认可与选择,那么它到底好在哪里,来看看这位车主怎么说。俗话说得好人靠衣装马靠鞍,二十一世纪那就是看脸的可可爱爱,比亚迪e1比亚迪e1,太q了,连我这个直男也被它迷惑到了。你有没有呢?听听车主怎么说,看看e1到底有什么过人之处!对于选车我想很多小伙伴都和我一样,不知该如何下手,不知该如何选择,这些都是我太可爱了!努比亚65W氮化镓充电器套装,真正的旅充一说到旅行,你脑海中除了美丽的风景诱人的美食独特的风土人情还有什么呢?是不是还有各种电子设备的充电器。今天我再给大家带来一款非常棒的,真正意义上的旅行充电器,折叠插脚多口快充哪个都怎么实现一个最小栈?实现一个栈,该栈带有出栈(pop)入栈(push)取最小元素(getMin)3个方法。要保证这3个方法的时间复杂度都是O(1)。如果用一个变量m保存栈的最小值,我们模拟一下入栈1入球迷们听好了!教你独赏世界杯的正确打开方式世界杯倒计时对于许多球迷而言,现在已经是可以按秒来算计了吧?世界杯一来,什么101,什么街舞团,什么奔跑吧统统给我靠边站,一箱啤酒,一拨基友,一台电视,才是我等球迷向往的生活!不过性能进阶京爆新品日首选华硕灵耀X系列轻薄本近日,华硕新品发布会上发布了多款新品,如天选2游戏本天选air创作本等,还有华硕旗下的灵耀X系列高端商务本,其中包括耀X纵横3。3K触控全面屏轻薄本灵耀X逍遥4KOLED触控翻转轻有一天,你可能会为当时的不舍得而买单大家好,我是老李。相信看到标题的时候,一定有不少朋友要吐槽老李是不是今天又要灌毒鸡汤了。其实并不是,只是正好看到一则广告文案,有感而发。当年嫌贵舍不得买空调,结果几年后熬不住,还是
从这个月开始,你每个月房贷利息要减少了大家好,我是老李。今天和大家聊聊房贷利息。2021年开始,房贷利率将正式变成新的形式LPR浮动利率。如果你的房贷利率转换日定在每年的1月1日,则从这个月开始,房贷利率将发生变化,进只赔2000元外卖员猝死背后的暴利生意大家好,我是老李。今天和大家聊聊外卖员猝死赔偿一事。前几天看到一个新闻,说是饿了么的一位43岁的外卖员在送餐途中突然猝死,他的家人们就向饿了么索要工伤赔偿,可是饿了么却坚称这位外卖阿里巴巴被查,放在支付宝里的钱还安全吗?大家好,我是老李。今天和大家聊聊被查的阿里巴巴。2020年年末,关于阿里巴巴的消息不断,几乎每一个消息曝出之后都成为了市场热点,毕竟阿里巴巴作为如今世界级的巨头企业,人们的衣食住行最猛股市退市新规来袭,A股股民应该注意什么?大家好,我是老李。今天和大家聊聊最新的股市退市新规。自从注册制落地以来,备受关注的退市新规也终于要来了。8年以来,力度最大级别也最高的这次改革,对于A股股民来说到底应该注意什么呢?银行存款大变天,利息可能少10倍大家好,我是老李。今天和大家聊聊银行存款。虽然说如今随着广大老百姓理财意识的提升,以及市场上日益丰富的投资产品的出现,原先存进银行的大量存款已经转移去了股票基金等金融资产上。但如今存钱最好的方式,90的人却不知道大家好,我是老李。今天和大家聊聊存钱的方式。老李认为存钱应该是我们每个人都必须掌握的技能。钱是一个人生活的必备品,也是一个人的底气,更是创造财富的铺路石。但是老李身边依然有不少人不注册制加快推进,投资策略要改了大家好,我是老李。今天和大家聊聊推进全面注册制一事。全面注册制要比预期的来得要更快了!据国际金融报报道,一位沪深证券交易所的相关人士向记者表示,全市场推行注册制的条件已经初步成型,关于这两天的股市大暴跌大家好,我是老李。今天和大家聊聊这两天的股市暴跌。先来说一下这一轮股市上涨的行情,从2020年11月2日起,A股从3225点开始启动,一直上涨至周一的3624点,在接近3个月的时间重疾新规落地后,女性保费怒涨20?男性保费暴涨15?大家好,我是老李。今天和大家聊聊重疾新规落地后保费涨价一事。最近在精算圈子有一张被称为内幕消息的图在疯狂传播。那么这个消息到底是真还是假呢?于是老李我就去中国精算师协会查询了一下最牛市行情那么好,还买什么年金险!?大家好,我是老李。今天和大家聊聊如何看待投资的收益性和稳健性。最近A股的行情相信让不少人有了自己是巴菲特在世的错觉。甚至有一部分人自信的认为,通过股票基金等权益类投资,就能让自己拥百万医疗险都能保证续保20年了,还有必要买重疾险吗?大家好,我是老李。今天和大家聊聊长期医疗险。前段时间,有几家保险公司陆陆续续的推出了保证长期续保的百万医疗险,最长能保证续保20年。于是,有不少朋友来问既然百万医疗险的保费那么便宜