当前位置: 首页 > Web前端 > HTML

了解Promise

时间:2023-04-03 00:55:48 HTML

inJavascript阿里云目前正在做活动,低至20折,有兴趣的可以看看:https://promotion.aliyun.com/...为了保证可读性,本文采用意译非直译。想阅读更多优质文章,请戳GitHub博客,一年百篇优质文章等你来!背景当您第一次开始使用JavaScript时,可能会有些沮丧。您会听到有人说JavaScript是一种同步编程语言,而其他人则认为它是异步的。您将了解到阻塞代码、非阻塞代码、事件驱动设计模式、事件生命周期、函数堆栈、事件队列、冒泡、polyfill、babel、angular、reactJS、vueJS以及大量其他工具和库。别担心,你不是第一个。这也有一个术语,叫做JavaScript疲劳。JavaScript疲劳:JavaScript疲劳发生在人们使用他们不需要的工具来解决他们没有的问题时JavaScript是一种同步编程语言。但是多亏了回调函数,我们可以让它像异步编程语言一样工作。初学者的承诺JavaScript中的承诺与现实生活中的承诺非常相似。首先让我们看看现实生活中的承诺。字典中承诺的定义:保证某人会做某事或某事会发生。那么当有人答应你时会发生什么?承诺给你保证某事会发生。他们(做出承诺的人)是自己做还是别人做并不重要。他们给你一个保证,你可以据此计划一些事情。承诺可以保持或打破。当诺言被遵守时,你对它有什么期望。您可以使用承诺的结果来制定进一步的行动或计划。当诺言被打破时,你想知道为什么许下诺言的人不能信守诺言。一旦知道原因并确认承诺已被打破,您就可以计划下一步该做什么或如何处理它。在做出承诺时,我们拥有的只是保证。我们不能立即采取行动。我们可以决定并制定在遵守诺言(因此我们得到期望的结果)或违背诺言(我们知道原因,因此我们可以为意外事件做计划)时需要做什么。您很可能根本就没有收到受诺人的回音。在这种情况下,您宁愿保留一个时间阈值。如果许下诺言的人10天后没有回来找我,我就认为他有问题,不会信守诺言。因此,即使那个人在15天后回到你身边,对你来说也不再重要,因为你已经有了其他计划。JavaScript中的承诺根据经验,对于JavaScript,我总是阅读MDNWeb文档中的文档。在所有资源中,我认为它们提供了最简洁的细节。我从MDSN网络文档中阅读了对promises的介绍,并尝试了一些代码来掌握它。理解承诺有两个部分。“创造承诺”和“解决承诺”。虽然我们的大部分代码通常用于处理由其他库创建的promise,但它肯定有助于充分理解这些promise。一旦你超过了初级水平,理解“创造承诺”同样重要。Promise创建让我们看一下创建新Promise的语法构造函数接受一个名为executor的函数。这个执行函数接受两个参数,resolve和reject,都是函数。Promises通常用于更容易地处理异步操作或阻塞代码,其示例包括文件操作、API调用、DB调用、IO调用等。这些异步操作的启动发生在execute函数中。如果异步操作成功,承诺的创建者将调用resolve函数返回预期的结果。同样,如果发生意外错误,错误特定信息将通过调用reject函数传递。varkeepsHisWord;keepsHisWord=true;promise1=newPromise(function(resolve,reject){if(keepsHisWord){resolve("小智承诺会一直把好东西分享给大家");}else{reject("我没有做!");}});控制台日志(承诺1);由于promise是立即执行的,我们将无法检查promise的初始状态。所以让我们创建一个需要时间来实现的承诺,最简单的方法是使用setTimeOut函数。promise2=newPromise(function(resolve,reject){setTimeout(function(){resolve({message:"小智承诺把好东西分享给大家",code:"200"});},10*1000);});控制台日志(承诺2);上面的代码只是创建了一个在10秒后无条件履行的承诺。因此,我们可以检查承诺的状态,直到它被解决。一旦十秒过??去,承诺就解决了。PromiseStatus和PromiseValue都会相应更新。如您所见,我们更新了resolve函数以传递JSON对象而不是简单的字符串。这只是为了说明我们也可以在resolve函数中传递其他值。现在让我们看一个拒绝承诺的例子。我们只需要修改keepsHisWord:我们可以看到PromiseStatus可以有三个不同的值,pending(进行中),resolved(成功)或者rejected(失败)。创建承诺时,PromiseStatus将处于未决状态并且PromiseValue将是未定义的,直到承诺被解决或拒绝。当承诺处于已解决或已拒绝状态时,它被称为已解决。所以promises通常会从pending状态过渡到settled状态。现在我们知道了如何创建承诺,我们可以看看如何使用或处理承诺。这将与理解Promise对象密切相关。理解Promise对象根据MDN文档,Promise对象表示异步操作最终完成(或失败)及其结果值。Promise对象有静态方法和原型方法。Promise对象中的静态方法可以独立应用,原型方法需要应用到Promise对象中。实例。请记住,普通方法和原型都返回一个romise,这使得理解事情变得容易得多。原型方法(PrototypeMethods)让我们先从原型方法说起,一共有三个方法。重申一下,请记住所有这些方法都可以应用于Promise对象的实例,并且所有这些方法依次返回一个Promise。以下所有方法都为promise的不同状态转换分配处理程序。正如我们之前看到的,当Promise创建时,它处于pending状态。根据Promise是fulfilled(成功)还是rejected(失败),将运行以下三种方法中的一种或多种。Promise.prototype.catch(onRejected)Promise.prototype.then(onFulfilled,onRejected)Promise.prototype.finally(onFinally)下图显示了then和.catch方法的流程。因为他们返回了一个Promise,所以他们可以再次被链接起来。无论promise的最终状态如何,then或catch指定的回调函数执行完毕后,finally方法指定的回调函数将被执行。这是一个小故事。你是一个在学校的孩子,你向你妈妈要了一个电话。她说:“我打算这个月底去买一部手机。”如果承诺在月底执行,让我们看看在JavaScript中会是什么样子。varmomsPromise=newPromise(function(resolve,reject){momsSavings=20000;priceOfPhone=60000;if(momsSavings>priceOfPhone){resolve({brand:"iphone",model:"6s"});}else{reject(“我们没有足够的积蓄,让我们多存点钱吧。");}});momsPromise.then(function(value){console.log("哇,我得到了这个手机作为礼物",JSON.stringify(value));});momsPromise.catch(function(reason){console.log("妈妈不能给我买手机因为",reason);});momsPromise.finally(function(){console.log("不管妈妈能不能给我买手机,我还是爱her");});输出:如果我们将妈妈的礼物的价值改为200,000美元,那么妈妈可以为她的儿子买礼物。在这种情况下,输出将是then方法的第一个参数是已解决的状态回调函数,第二个参数(可选)是被拒绝状态的回调函数。所以我们也可以这样写:但是为了代码的可读性,我觉得最好把它们分开。保证我们可以在浏览器运行所有这些示例,或chrome中的特定示例,我想确保我们的代码示例中没有外部依赖项。为了更好地理解进一步的主题,让我们创建一个将返回Promise的函数,该函数随机执行resolve或拒绝,以便我们可以测试各种场景。由于我们需要随机数,因此让我们首先创建一个随机函数,它将返回x和y之间的随机数。让我们创建一个函数来返回承诺。让我们调用promiseTRRARNOSG函数,它是promiseThatResolvesRandomlyAfterNumnberOfSecondsGenerator的别名。此函数将创建一个承诺,该承诺将在2到10秒之间的随机秒数后解决或拒绝。为了随机解析和拒绝,我们将创建一个介于1和10之间的随机数。如果生成的随机数大于5,我们将执行解析,否则执行拒绝。functiongetRandomNumber(start=1,end=10){//当start和end都>=1时有效return(parseInt(Math.random()*end)%(end-start+1))+start;}varpromiseTRRARNOSG=(promiseThatResolvesRandomlyAfterRandomNumnberOfSecondsGenerator=function(){returnnewPromise(function(resolve,reject){letrandomNumberOfSeconds=getRandomNumber(2,10);setTimeout(function(){letrandomiseResolving=getRandomNumber(1,10);如果(randomiseResolving>5){resolve({randomNumberOfSeconds:randomNumberOfSeconds,randomiseResolving:randomiseResolving});}else{reject({randomNumberOfSeconds:randomNumberOfSeconds,randomiseResolving:randomiseResolving});}},randomNumberOfSeconds*1000);});});vartestProimse=promiseTRRARNOSG}();testProimse.then(function(value){console.log("解决promise时的值:",value);});testProimse.catch(function(reason){console.log("Reasonwhenpromiseisrejected:",reason);});//创建10个不同的promisefor(i=1;i<=10;i++){letpromise=promiseTRRARNOSG();promise.then(function(value){console.log("解决promise时的值:",value);});promise.catch(function(reason){console.log("reasonwhenpromiseisrejected:",reason);});}刷新浏览器页面,在控制台运行代码,可以看到resolve和reject的不同输出场景静态方法Promise对象中有四种静态方法。前两个是辅助方法或快捷方式。它们可以帮助您轻松创建已解决和拒绝的方法。Promise.reject(reason):Promise.resolve(value):附带说明,promise可以有多个处理程序。因此,您可以将上面的代码更新为:output:以下两个方法可以帮助您处理一组promise。当您处理多个promise时,最好先创建一个promise数组,然后对这组promise执行必要的操作。为了理解这些方法,我们不能在上面的例子中使用promiseTRRARNOSG,因为它太随机了,最好有一些确定性的promise,这样我们才能更好地理解promise行为。让我们创建两个函数。一个在n秒后执行resolve,另一个在n秒后执行reject。现在让我们使用这些辅助函数来理解Promise.AllPromise.All根据MDN文档:Promise.all(iterable)方法返回一个Promise实例,其中可迭代参数中的所有承诺都被“解决”或参数中的任何承诺都没有当包含承诺时,回调完成(解决);如果参数中的一个承诺失败(拒绝),则实例回调失败(拒绝),失败原因是第一个失败承诺的结果。示例1:当所有的promise都被fulfill时,这是最常见的场景。我们需要从输出中得出两个重要结论:第三个promise需要2秒才能完成,第二个promise需要4秒。但正如您在输出中看到的那样,承诺的顺序保留在值中。我添加了一个计时器来确定承诺需要多长时间才能实现。如果按顺序履行承诺,总共需要1+4+2=7秒,但从计时器我们看到只需要4秒。这证明所有的承诺都是并行执行的。示例2:当数组不是promise时怎么办?(我认为这是最不常见的)输出:由于数组中没有promise,因此会执行promise中的resolve。示例1:其中一个承诺首先处于解析状态。Promise.race根据MDN:Promise.race(iterable)方法返回一个承诺。一旦迭代器中的承诺被解决或拒绝,返回的承诺将被解决或拒绝。constp=Promise.race([p1,p2,p3]);上述代码中,只要p1、p2、p3中有一个实例先改变状态,p的状态就会随之改变。第一个变异的Promise实例的返回值被传递给p的回调函数。所有承诺并行运行。第三个承诺在2秒内解决,因此第一个更改返回给Promise.race。示例2:其中一个承诺首先处于拒绝状态。所有的承诺都在并行运行。第四个承诺在3秒内解决,因此第一个更改返回给Promise.race。使用承诺的经验法则使用异步或阻塞代码时,请使用承诺。为了代码的可读性,resolve方法对待then,reject对应catch。确保同时编写.catch和.then方法来实现所有承诺。如果在这两种情况下都需要做某事,请使用.finally。我们只改变每个承诺一次(单一原则)。我们可以向承诺添加多个处理程序。Promise对象中所有方法的返回类型,无论是静态方法还是原型方法,都是Promise。在Promise.all中,无论哪个promise先未实现,promise的顺序都保存在value变量中。原文:https://hackernoon.com/unders...你的点赞是我继续分享好东西的动力,欢迎点赞!笨码农,Minecraft终生只能学习!干货交流系列文章总结如下。我觉得点个Star就好了。欢迎加群,互相学习。https://github.com/qq44924588...我是小智,公众号《大招天下》的作者,前端技术爱好者。我会经常分享自己学习看到的干货,在进步的路上互相鼓励!关注公众号,后台回复福利,就能看到福利,你懂的。