promise等是一种美也痛_第1页
promise等是一种美也痛_第2页
promise等是一种美也痛_第3页
promise等是一种美也痛_第4页
promise等是一种美也痛_第5页
已阅读5页,还剩25页未读, 继续免费阅读

付费下载

下载本文档

版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领

文档简介

Promise等待的Java&Nodejs“铁和人海,我排着队拿著爱的号码牌”——《遇见》2015就要结束,终于舍得花点时间去整理一些文章,做一些记单线程和事件JS的一大特色,JS中的IO都是非阻塞的,所以异步编程对于JS编程是极其重要的。传统的方式是使用回调,这样的方式会导致回调黑洞,且不利于阅读。所以新的JS规范出现了Promise,Generator和Asyncawait,使得异步编程更容易。由于Promise应用还不是很广泛,本文参考的资料主要是英文CommonJS之Promises/A规范,通过规范API接口来简化异步编程,使的异步逻辑代码更易理解。文档https:/ 中文翻译 Promises/A+规范的实现有很JQuery的deferred bluebird模块 q模块 async模 本文主要介绍ES6规范的Promise对Promise一个Promse实例对象,表示一次异步操作的封装,异步操作同的操作。并且可以多个Promse串联起来使用,也就是把异步操作串联起来,组织成并发或者串行工作流等。通过Promse可以把复杂的异步代码看起来更简洁,理解起来更容易。生成PromisePromise对象是一个构造器函数对象,在使用Promise之前,需要先生成一个Promise对象的实例对象。letpromise=newPromise(function(resolve,reject)if·){resolve(value);//}elsereject(reason);//

需要传入一个固定格式的函数作为参数reject一般情况下,按照这一标准格式去使用,在这个参数函数体中,编写异步操作代码。然后根据异步操作的结果判断,如果成功,则调用resove,否则调用reect。可以这样理解:一次异步执行,首先等得到异步执行的结果,然后根据结果决定下一步做什么,这和流程图的步骤类似。resolve和reject都是提供的方法,Promise实例对象是引擎自动调用的,所以这两个参数有JS提供,直接使用就可以将Promise对象的状态从“未完成”变为“成功”(即从变为Resolved)。并把Promise实例对象的value设置为value。之后会调用then方法中的onFulfilled。将Promise对象的状态从“未完成”变为“失败”(即从Pending变为Rejected)。并把Promise实例对象的reason设置为参数reason。之后会调用then方法中的onRejected。小样:Promise生成的实例对象会被系统异步自动调生成Promise实例对象后,function(resolve,reject参数会被模拟了一次生成Promise实例对象,根据打印的结果,发现,function(resolve,reject被自动调用了,但是这不能确定这结论:function(resolve,reject是系统自动异步调用的,具体时使用了setTimeout模拟了一次异步操作,把它封装到一个Promise实例对象中。当异步操作完成,使用resolvepm状态修改为resolved,并且把pm的值设置”success”。promise.then(onFulfilled,then方法用来Promise实例对象状态从pending变成其他状态后调用的回调函数。onFulfilledonRejected都必须为函数。then参数onFulfilled:可选参数,函数Promise实例对象从pending变成fulfilled状态,之后会使用Promise实例对象的value调用onFulfilled。例如:在function(resolve,reject){}调用onRejected:可选参数,函数,Promise实例对象从pending变成rejected状态,之后会使用Promise实例对象的reason调用onRejected。例如:在function(resolve,reject){}调用reject返回值:then方立即返回一个新的Promise实例对象。当onFulfilledonRejected返回值是Promise实例pm的时候,then返回的Promise实例的状态会由pm的状态决定,详细请参照Promise规范,知道这点非常重要!promise.catchrejection方法是promisethennull,catch用于指定发生错误时的回调函数。在Promise实例对象的状态变成fulfilled或者rejected之前,只要发生错误,就会执行这个参数和返回值和then类似小样:then(onRejected)和catch(onRejected)的异抛出的异常不onRejected捕获,却可以被catch捕获。所以最佳实践是:使用catch而不是onRejected,避免有些异常不小样:异常冒异常会向下冒泡,直到遇到catch,中间的then会被忽略Promise.把value转换成Promise。一般用来把一个对象方便转换成实例对象。TJ的CO模块就用到了这个方法可以这样理解newPromise(resolve=>参数(1)value:可选。可以是任意的JavaScript合法值返回值如果value是非Promise实例对象,则返回一个新的Promise实例对象,且它的状态是fulfilled,它的值value;如果value是一个Promise实例对象,那么返回的也是这个实例对象。小样:value为非Promise实例不管是value是一般对象还是函数对象,都作为Promise实例小样:value为Promise实例对当value为Promise实例对象的时候,返回的是自己Promise.rejectreject和resolve是类似的,请参照resolve做类推用于将多个Promise实例,包装成一个新的Promise实例参数:一个包含Promise实例对象的迭代器。例如数组[p1,p2,返回值:一个新的Promise实例对象pm*pm状态由参数中的所有Promise实例对象的状态决当参数中所有的Promise实例对象的状态为fulfilled的时候,pm的状态为fulfilled。所有参数Promise实例对象的返回值组成一个数组,作为pm的值。当参数中的Promise实例对象有一个的状态为rejected的时候,它的状态为rejected。此时第一个被reject的Promise实例对象的返回值作为pm的reason。小样:所有参数的Promise实例对象的状态都为小样:有一个参数的Promise实例对象的状态为用于将多个Promise实例,包装成一个新的Promise实例参数:一个包含Promise实例对象的迭代器。例如数组[p1,p2,返回值:一个新的Promise实例对象pm*pm状态由参数中的第一个改变状态的Promise实例对象的状态决如果第一个改变的状态为fulfilled,那么pm的状态为fulfilled,并且pm的值为第一个改变状态的Promise实例对象的值。如果第一个改变的状态为rejected,那么pm的状态为reject,并且pm的reason为第一个状态改变的Promise实例对象的值。小样:第一个改变的状态为使用setTimeout函数,让pm2pm1延迟一秒修改状态。pm1在一秒后状态变为fulfilled,此时pms的状态也跟着变为fulfilled,已经不需要考虑pm2的执行。小样:第一个改变的状态为使用setTimeout函数,让pm1pm2延迟一秒修改状态。pm2在一秒后状态变为rejected,此时pms的状态也跟着变为rejected,已经不需要考虑pm1的执行。Promise前面已经详细介绍了Promise的作用和PromiseAPI使用。偶然的机会,发现了JakeArchibald非常棒的Promise实践例首先是基于Promise实现的ajax异步加载数据的实现,然后在Ajaxfunctionfunctionget(url)//ReturnanewreturnnewPromise(function(resolve,reject)//DotheusualXHRvarreq=newXMLHttpRequest();req.open('GET',url);req.onload=function(){//Thisiscalledevenon404//sochecktheif(req.status==200)//Resolvethepromisewiththeresponse}else//Otherwiserejectwiththestatus//whichwillhopefullybeameaningful}//Handlenetworkreq.onerror=function(){reject(Error("NetworkError"));//Makethe}定义了一个get函数,传入一个url,并返回一个Promise对象。正如前面强调的一样,Promise实例对象代表一次完整的异步操作过程。把异步代码放在function(resolve,reject){}中。最根据ajax的status也就异步操作的结果,决定ajax是否成功执行通过这样巧妙的异步代码封装到Promise实例对象中,实现了ajax操作Promise化,可以实现链式使用。避免了传统的只能小样:链式调get('story.json').then(function(response)get('story.json').then(function(response){returnJSON.parse(response);}).then(function(response){console.log("YeyJSON!",response);实现了ajax的链式调用后,发现代码阅读更美观,理解起来比使用原来的回调好了很多。第一步,加载了story.json的数据;第二步,把数据转换成JSON格式;第三步,把JSON数据打印出来。由于后面的例子都是使用JSON数据,所以需要对get进一步拓展,直接返回JSON数据:functionfunctiongetJSON(url)return}的顺序执行。例如:Tsk1——>Tsk2——>Tsk3……。例如:需要查询一个用户名为Weber用户写过的文章。第一步:到数据库查找username为Weber的用户;第二步:根据Weber的用户id到数据查找Weber的文章。第三步:返回Weber的用户信息和Weber的文章。在va这样的IO阻塞语言中很好实现,直接按照步骤写代码即可。但是在S入回调函数处理结果。JS使用传统方式实现需求functionfunctiongetPostsByUserName(name,response)db.findUserByName(‘weber’,function(user)db.findPostByUserId(user.id,function(posts)response.json(‘userPosts’,{user:user,}解,容易造成”回调黑洞。下面来看Promise实现异步任务顺序执行的例业务需求:使用Ajax加载一篇文章信息story.json,文章信息包含各个段落的基本信息,需要在获取。要求在页面按照1,2,3这第一步:取得文章列表第二步:按照story.json文章段落列表的顺序,加载段落并按照顺第二步可以看做一个整体,继续细:加载第一段:加载第二段:加载第三段n:以此类推getJSON('story.json').then(function(story)getJSON('story.json').then(function(story){returnstory.chapterUrls.reduce(function(sequence,chapterUrl){returnsequence.then(function()//……获取下一return}).then(function(chapter)}).then(function(chapter)//},}).then(function()//addTextToPage("All}).catch(function(err)//addTextToPage("Argh,broken:"+}).then(function()spinner.querySelector('.spinner').style.display=上述代码的效果图(请另预览git,2-2……先后的顺序,每个Promise实例是一个异步操作,必须是前一个Promise实例完成(fulfilled或者rejected)后一个才进行。这里巧妙的使用了promise.then方法实现了这样的控制。then方法会立即返回一个新的Promise实例对象pm1,在onFulfilled中返回下一个获取章节的Promise实例对象pm2,pm2决定了pm1的状态,也就是pm1的then方法需要pm2的状态确定了才会执行。以此推理,这样每个加载章节的Promise实例就被加上前一个控制后一个的限制getJSON('story.json').then(function(story)//接受一个Promise数组 return把章节URL数组转换成对应的Promise数}).then(function(chapters)//现 有了顺序的章节JSON,遍历它们chapters.forEach(function(chapter)//……并添加到页面addTextToPage("All}).catch(function(err)//捕获过程中的任何错addTextToPage("Argh,broken:"+}).then(function().querySelector('.spinner').style.display.querySelector('.spinner').style.display=上述代码的效果图(请另预览git3.2实现了异步任务的顺序执行,但是异步IO是很耗时的,假所以,在有些情况下,需要像多线程一样,并发执行很多任务,用资源换取时间。庆幸的是,浏览器是支持ax多任务并发执行的。现在3.2的业务要求不变,换种方法实现。注意到,业务要每个Promise实例对象表示一次异步操作,现在把ajaxPromise化了,现在同时有多个异步任务,也就是多个Promise实例对象需要处理,没错,Promise.all上场了。Promise.all中的Promise实例是并行执行的,在所有Promise实例的状态都为fulfilled的情况,Promise实例返回的值的顺序也是但是Promise.all也有个问题,假如其中一个ajax请求失败,那么整体的Promise实例就被rejected,一个任务失败导致全部段落其实很简单:让所有的Promise无论如何都是fulfilled就好if(req.status==200)以响应文本为结果,完Promise}elseresolve(‘loadingerror:’+req.statusText);}方法有些,但是还是实用的,渲染了其他数据,又给了户错误信息提示。某些情况下,这种方法用来避免Promise.all的这样的问题还是3.1顺序执行效率低,3.2并行执行但是需要所有的数据加载完getJSON('story.json').then(function(story)getJSON('story.json').then(function(story){//Mapourarrayofchapterurls//anarrayofchapterjson//Thismakessuretheyalldownloadreturn.reduce(function(sequence,chapterPromise)//Usereducetochainthepromises//addingcontenttothepageforeachreturnsequence.then(function()//Waitforeverythinginthesequenceso//thenwaitforthischaptertoreturn}).then

温馨提示

  • 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
  • 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
  • 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
  • 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
  • 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
  • 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
  • 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

评论

0/150

提交评论