说明你最近在复习Promise的知识,所以做了一些题。这里有几个问题,一起来看看吧。话题一constpromise=newPromise((resolve,reject)=>{console.log(1);resolve();console.log(2);})promise.then(()=>{console.log(3);})console.log(4);分析首先,Promise创建后立即执行,所以会先输出1、2,Promise.then()里面的代码在当前结束后立即执行eventloop,所以会一直输出4,最后输出3回答1243问题2constpromise=newPromise((resolve,reject)=>{resolve('success1');reject('error');resolve('success2');});promise.then((res)=>{console.log('then:',res);}).catch((err)=>{console.log('catch:',err);})resolve函数将Promise对象的状态从“notCompleted”变为“successful”(即从pending变为resolved),当异步操作成功时调用,异步操作的结果为作为参数传递;reject函数将Promise对象的状态从“unfinished”变为“Failed”(即从pending变为rejected),在异步操作失败时调用,将异步操作报错作为参数传递.而且状态一旦改变,就不会再改变了。所以拒绝('错误');在代码中将不起作用。一个Promise只能被解决一次,其余的调用将被忽略。所以第二个resolve('success2');也不会工作。Answerthen:success1题目3Promise.resolve(1).then(2).then(Promise.resolve(3)).then(console.log)如果Promise.resolve方法的参数是一个原始值或者一个Foran对于没有then方法的对象,Promise.resolve方法返回一个新的状态为resolved的Promise对象,同时Promise.resolve方法的参数会传递给回调函数。then方法接受的参数是一个函数,如果不是函数,它实际上会解释为then(null),这样会导致前面Promise的结果穿透到下面。回答1问题4红灯每三秒亮一次,绿灯每秒亮一次,黄灯每两秒亮一次;如何让三个灯交替反复亮起?(用Promse实现)三个灯光功能已经存在:参考前端高级面试题的详细解答functionred(){console.log('red');}functiongreen(){console.log('green');}functionyellow(){console.log('yellow');}分析红灯每三秒亮一次,绿灯每秒亮一次,黄灯每两秒亮一次,也就是说为3秒,红色功能执行一次,2秒内执行一次绿色功能执行一次,黄色功能每秒执行一次,灯交替反复点亮,表示这3个函数始终按此顺序执行。这一步可以使用递归来实现。答案functionred(){console.log('red');}functiongreen(){console.log('green');}functionyellow(){console.log('yellow');}varlight=function(timmer,cb){returnnewPromise(function(resolve,reject){setTimeout(function(){cb();resolve();},timmer);});};varstep=function(){承诺。resolve().then(function(){returnlight(3000,red);}).then(function(){returnlight(2000,green);}).then(function(){returnlight(1000,yellow));}).then(function(){step();});}step();Topic5实现mergePromise函数,依次执行传入的数组,将返回的数据放入数组data中。consttimeout=ms=>newPromise((resolve,reject)=>{setTimeout(()=>{resolve();},ms);});constajax1=()=>timeout(2000).then(()=>{console.log('1');return1;});constajax2=()=>timeout(1000).then(()=>{console.log('2');return2;});constajax3=()=>timeout(2000).then(()=>{console.log('3');return3;});constmergePromise=ajaxArray=>{//在这里实现你的代码};mergePromise([ajax1,ajax2,ajax3]).then(data=>{console.log('done');console.log(data);//datais[1,2,3]});//需要单独输出//1//2//3//done//[1,2,3]分析首先,ajax1、ajax2、ajax3是所有的函数,但是这些函数执行后会返回一个Promise,按标题要求我们只需要依次执行这三个函数,然后把结果放入data即可,但是这些函数都是异步操作,并不是这样的简单的依次执行它们,然后输出1、2、3。看一个例子。functionA(){setTimeout(function(){console.log('a');},3000);}functionB(){setTimeout(function(){console.log('b');},1000);}A();B();//b//在a的例子中,我们依次执行A和B,但是输出结果是b,a。对于这些异步函数,它们不会按照顺序先执行一个,再执行后一个。这道题是用Promise来控制异步过程。我们得想办法让这些函数一个执行完再执行下一个。让我们看看答案。Answer//将函数执行结果保存在数组中vardata=[];//无参调用Promise.resolve方法,直接返回一个已解析状态的Promise对象。varsequence=Promise.resolve();ajaxArray.forEach(function(item){//第一个then方法用于执行数组中的每个函数,//第二个then方法接受数组中的函数执行然后返回result,//并将结果添加到data中,然后返回数据。//这里对sequence的重新赋值其实相当于扩展Promise链sequence=sequence.then(item).then(function(res){data.push(res);returndata;});})//遍历后返回一个Promise,即sequence,其[[PromiseValue]]值为data,//和data(保存数组后的结果)functionin被执行)也将作为参数传递给下一次调用的then方法。返回序列;问题6以下代码的最终输出是什么?constfirst=()=>(newPromise((resolve,reject)=>{console.log(3);letp=newPromise((resolve,reject)=>{console.log(7);setTimeout(()=>{console.log(5);resolve(6);},0)resolve(1);});resolve(2);p.then((arg)=>{console.log(arg);});}));first().then((arg)=>{console.log(arg);});console.log(4);分析这个问题其实和Promise关系不大,主要是需要了解JS的执行机制,才能很好的解决这个问题。不了解JS执行机制的朋友推荐阅读这篇文章。这一次,彻底了解JavaScript的执行机制。第一轮事件循环首先执行宏任务。主脚本,立即执行newPromise,输出[3],执行p的newPromise操作,输出[7],找到setTimeout,将回调放入下一轮任务队列(EventQueue),然后p的,让我们调用then1,放入microtask队列,找到第一个then,调用then2,放入microtask队列。执行console.log(4),输出[4],宏任务执行结束。然后执行microtask,执行then1,输出[1],执行then2,输出[2]。至此,第一轮事件循环结束。开始第二轮。第二轮事件循环先执行宏任务,即setTimeout的回调,输出[5]。resolve(6)不会生效,因为Promisep的状态一旦改变就不会改变。答374125第7题有8个图片资源的url,已经存储在数组urls中(即urls=['http://example.com/1.jpg',....,'http://example.jpg',....,'http://example.com/8.jpg']),并且已经有一个函数functionloadImg,输入一个url链接,返回一个Promise,图片下载完成时resolve,下载失败则reject。但是我们要求在任何时候,同时下载的链接数不能超过3个。请写一段代码来实现这个要求,要求所有图片尽快下载完毕。varurls=['https://www.kkkk1000.com/images/getImgData/getImgDatadata.jpg','https://www.kkkk1000.com/images/getImgData/gray.gif','https://www.kkkk1000.com/images/getImgData/Particle.gif','https://www.kkkk1000.com/images/getImgData/arithmetic.png','https://www.kkkk1000.com/images/getImgData/arithmetic2.gif','https://www.kkkk1000.com/images/getImgData/getImgDataError.jpg','https://www.kkkk1000.com/images/getImgData/arithmetic.gif','https://p1-jj.byteimg.com/tos-cn-i-t2oaga2asx/gold-user-assets/2018/10/29/166be40ccc434be0~tplv-t2oaga2asx-image.image'];functionloadImg(url){returnnewPromise((resolve,reject)=>{constimg=newImage()img.onload=function(){console.log('animageloaded');resolve();}img.onerror=rejectimg.src=url})复制代码};解析标题的意思就是我们需要这样做,先并发请求3张图片,当一张图片加载完成后,会继续发起请求另一张图片,保持并发数为3,直到需要加载为止发起所有请求的图片。用Promise实现就是先并发请求3个图片资源,这样就可以得到3个Promise组成一个数组,称为promises,然后不断调用Promise.race返回状态变化最快的Promise,然后从arraypromises),然后添加一个新的Promise,直到所有的url都被抓取,最后使用Promise.all处理数组(promises)中没有改变状态的Promise。答案varurls=['https://www.kkkk1000.com/images/getImgData/getImgDatadata.jpg','https://www.kkkk1000.com/images/getImgData/gray.gif','https://www.kkkk1000.com/images/getImgData/Particle.gif','https://www.kkkk1000.com/images/getImgData/arithmetic.png','https://www.kkkk1000.com/images/getImgData/arithmetic2.gif','https://www.kkkk1000.com/images/getImgData/getImgDataError.jpg','https://www.kkkk1000.com/images/getImgData/arithmetic.gif','https://p1-jj.byteimg.com/tos-cn-i-t2oaga2asx/gold-user-assets/2018/10/29/166be40ccc434be0~tplv-t2oaga2asx-image.image'];functionloadImg(url){returnnewPromise((resolve,reject)=>{constimg=newImage()img.onload=function(){console.log('图片已加载');resolve();}img.onerror=rejectimg.src=url})};functionlimitLoad(urls,handler,limit){//复制数组constsequence=[].concat(urls)letpromises=[];//最大并发请求数promises=sequence.splice(0,limit).map((url,index)=>{//这里返回的index是promises中task的下标,用于查找Promise.racereturn后完成的task下标处理程序(url).then(()=>{returnindex});});//使用数组的reduce方法以队列的形式执行returnsequence.reduce((last,url,currentIndex)=>{returnlast.then(()=>{//返回变化的Promisestate最快returnPromise.race(promises)}).catch(err=>{//这里的catch不仅仅用来捕捉前面的then方法抛出的错误//更重要的是防止整个链条被打断console.error(err)}).then((res)=>{//用新的Promise替换状态变化最快的Promisepromises[res]=handler(sequence[currentIndex].then(()=>{returnres});})},Promise.resolve()).then(()=>{returnPromise.all(promises)})}limitLoad(urls,loadImg,3)/*因为limitLoad函数也返回一个Promise,当所有图片加载完成后,可以继续链式调用limitLoad(urls,loadImg,3).then(()=>{console.log('Allimagesareloaded');})。catch(err=>{console.error(err);})*/总结这几题,有的考Promise的基础知识,有的考Promise的灵活运用。如果你在这些问题上做得很好,那么你对Promise的理解应该很好。最后,文中如有不足或错误之处,请指出,万分感谢。如果觉得文章内容不够,文末有与主题相关的文章,可以看看。
