作者:MahdhiRezvi译者:前端小智来源:medium有梦想,有干货,微信搜索【大千世界】追踪这位凌晨还在洗碗的洗碗智慧。本文已收录到GitHubhttps://github.com/qq449245884/xiaozhi,里面有完整的测试站点、资料和我的一线厂商访谈系列文章。JS自1996年发布以来一直在稳步改进。随着ECMAScript版本的许多改进,最新版本是ES2020。JS的一个重大更新是Promises,它于2015年以ES6的名义发布。什么是Promises?MDN上对Promise的定义:Promise对象用于表示一个异步操作的最终完成(或失败)及其结果值。对于新手来说,这听起来有点太复杂了。一位外教对Promises的解释是这样的:“想象一下你是个孩子,你妈妈向你保证下周她会给你买一部新手机。”手机。要么你妈妈真的给你买了一部全新的手机,要么她不买是因为她不开心。这是一个承诺。一个Promise有三个状态。它们是:Pending:你不知道你能不能买到那部手机Fulfilled:我妈妈高兴,我给你买了它Rejected:我妈妈不高兴,我不会给你买的这是我听到的到目前为止,我可以理解它是最快的Promise实例。如果您还没有开始学习Promises,我建议您这样做。Promises包含几个非常有用的内置方法。今天我们主要介绍这两种方法。Promise.race()-与ES6Promise.any()一起发布-仍处于第4阶段提案中,可作为参数迭代。Promise.race(iterable)方法返回一个承诺,一旦迭代器中的承诺之一解决或拒绝,该承诺就会解决或拒绝。与Promise.any()方法不同,Promise.race()方法主要关注Promise是否被resolve,不管是resolved还是rejected。语法Promise.race(iterable)参数iterable—可迭代对象,类似于Array。可迭代对象实现Symbol.iterator方法。返回一个异步解决或拒绝的未决Promise(一旦堆栈为空),每当给定迭代中的一个承诺解决或拒绝时,将第一个承诺的值作为其值。请注意,因为参数接受一个可迭代对象,所以我们可以传递一些值,例如原始值,甚至是数组中的对象。在这种情况下,race方法将返回第一个通过的非承诺。这主要是因为该方法的行为是在值可用时(当promise被履行时)立即返回该值。此外,如果在可迭代对象中传递了一个已解析的Promise,则Promise.race()方法将解析为该值的第一个。如果传递了一个空的Iterable,则race方法将永远挂起。示例constpromise1=newPromise((resolve,reject)=>{setTimeout(resolve,500,'promise1resolved');});constpromise2=newPromise((resolve,reject)=>{setTimeout(reject,100,'promise2rejected');});constpromise3=newPromise((resolve,reject)=>{setTimeout(resolve,200,'promise3resolved')});(async()=>{try{letresult=awaitPromise.race([promise1,promise2,promise3]);console.log(result);}catch(err){console.错误(错误);}})();//输出-"promise2rejected"//虽然promise1和promise3resolve,但promise2比它们拒绝得更快。//因此Promise.race方法将拒绝使用promise2的真实用例现在,您可能想知道,我们在实践中什么时候使用Promise.race()?来看看。在请求数据时显示加载动画在使用加载动画的开发中很常见。当数据响应时间长的时候,如果不使用loading动画,会看起来像是没有响应。但有时,反应太快了。当我们需要加载动画的时候,加一个很小的延迟时间,会让用户觉得我在频繁请求。为此,只需使用Promise.race()方法,如下所示。functiongetUserInfo(user){returnnewPromise((resolve,reject)=>{//1500更逼真,但900更适合测试setTimeout(()=>resolve("userdata!"),Math.floor(900*Math.random()));});}functionshowUserInfo(user){returngetUserInfo().then(info=>{console.log("userinfo:",info);returntrue;});}functionshowSpinner(){console.log("请稍等...")}functiontimeout(delay,result){returnnewPromise(resolve=>{setTimeout(()=>resolve(result),delay);});}Promise.race([showUserInfo(),timeout(300)]).then(displayed=>{if(!displayed)showSpinner();});取消的Promise有一些情况下面,我们需要取消取消Promise,这个时候也可以借用Promise.race()方法:functiontimeout(delay){letcancel;constwait=newPromise(resolve=>{consttimer=setTimeout(()=>resolve(false),delay);cancel=()=>{clearTimeout(timer);resolve(true);};});wait.cancel=取消;返回等待;}函数doWork(){constworkFactor=Math.floor(600*Math.random());常量工作=超时(工作因素);constresult=work.then(canceled=>{if(canceled)console.log('Workcanceled');elseconsole.log('Workdonein',workFactor,'ms');return!canceled;});结果.取消=工作.取消;返回结果;}functionattemptWork(){constwork=doWork();returnPromise.race([work,ti??meout(300)]).then(done=>{if(!done)work.cancel();return(done?'Workcomplete!':'Igaveup');});}attemptWork().then(console.log);长时间执行的批处理请求ChrisJensen有一个有趣的race()方法用例,他使用Promise.race()方法对长时间运行的请求进行批处理。这样,他们可以保持并行请求的数量不变。const_=require('lodash')asyncfunctionbatchRequests(options){letquery={offset:0,limit:options.limit};做{batch=awaitmodel.findAll(query);query.offset+=options.limit;if(batch.length){constpromise=doLongRequestForBatch(batch).then(()=>{//一旦完成,从我们的数组中弹出这个promise//这样我们就知道我们可以在它的位置添加另一个批次_.remove(承诺,p=>p===承诺);});承诺。推(承诺);//一旦我们达到并发限制,在继续批处理请求之前等待至少一个承诺//解决if(promises.length>=options.concurrentBatches){awaitPromise.race(promises);}}}while(batch.length);//等待剩余批处理完成returnPromise.all(promises);}batchRequests({limit:100,concurrentBatches:5});Promise.any()Promise.any()接收一个Promise可迭代对象,只要其中一个promise成功,就返回成功的promise如果所有可迭代的promise都没有成功(即所有promisesallfail/reject),返回失败的承诺和AggregateError类型的实例,AggregateError是Error的子类,用于将单个错误聚合在一起。本质上,这个方法是Promise.all()的逆函数。注意!Promise.any()方法仍处于试验阶段,尚未得到所有浏览器的完全支持。目前在TC39Stage4语法草案中Promise.any(iterable);参数iterable—一个可迭代对象,例如Array。返回值如果传递的参数是一个空的可迭代对象,则返回一个状态为已拒绝的Promise。如果传递的参数不包含任何承诺,则返回一个异步解析的承诺。在所有其他情况下,将返回一个挂起的Promise。一旦传入迭代器中的任何一个承诺解决(解决),或者其中的所有承诺都失败(解决/拒绝)状态,返回的承诺就会异步解决(当调用堆栈为空时)。指示此方法用于返回第一个成功的承诺。此方法会在一个promise完成后立即终止,它不会等待所有其他promise完成。不像Promise.all()返回一组已解决的值(resolvedvalues),我们只得到一个成功值(假设至少有一个promise被resolved)。当我们只需要一个promise成功而不关心是哪个时,这种方法很有用。此外,与始终返回第一个结果值(已解决/拒绝)的Promise.race()不同,此方法返回第一个成功的值。此方法将忽略所有被拒绝的承诺,直到第一个承诺得到履行。示例constpromise1=newPromise((resolve,reject)=>{setTimeout(reject,100,'promise1rejected');});constpromise2=newPromise((resolve,reject)=>{setTimeout(resolve,400,'promise2在400ms时解决');});constpromise3=newPromise((resolve,reject)=>{setTimeout(resolve,700,'promise3在800ms时解决');});(async()=>{try{letvalue=awaitPromise.any([promise1,promise2,promise3]);console.log(value);}catch(error){console.log(error);}})();//Output-"promise2resolvedat400ms"从上面的代码可以看出,Promise.any()主要关注解析值。它忽略在100毫秒时拒绝的promise1,并考虑在400毫秒后解决的promise2的值。从最快的服务器检索资源的真实用例假设访问我们网站的用户可能来自世界各地。如果我们的服务器位于一个位置,那么响应时间将根据每个用户的位置而有所不同。但是如果我们有多台服务器,我们可以使用产生最快响应的那台。在这种情况下,可以使用Promise.any()方法从最快的服务器接收响应。我是小智,下次见!代码部署后可能存在的bug,无法实时获知。事后为了解决这些bug,花费了大量的时间在日志调试上。顺便推荐一个好用的bug监控工具Fundebug。原文:https://blog.bitsrc.io/introd...每周更新交流文章。可以微信搜索“大千世界”立即阅读更新(比博客早一两篇),这篇文章GitHubhttps://github.com/qq449245884/xiaozhi已经收录,还有我的很多文档已经整理好了。欢迎明星和完美。可以参考考点面试。另外关注公众号,后台回复福利就可以看到福利了。你知道。
