当前位置: 首页 > Web前端 > vue.js

前端面试问promise怎么办?

时间:2023-04-01 01:49:30 vue.js

前言Promise是面试中的一道经典题,一定要深入学习和理解!Promise有什么用?答:我们用它来解决异步回调问题。Pomise是ES6中新的异步编程解决方案。现在这个promise在面试中感觉就是“css清除浮动”,属于前端基础知识,答不上来就挂。本文大纲:1、promise的基本用法;2.PromiseA+手动实现3.promise使用有哪些坑promise.all回调地狱等;将其视为在某个未来结束的事件的容器。它有两个特点:1.promise的状态不受外界影响;2.promise的状态一旦改变,就不会再改变。可以先看promise的结构functionPromise(executor){varself=thisself.status='pending'//Promise的当前状态self.data=undefined//Promise的值self.onResolvedCallback=[]//当Promiseresolve时设置的回调函数,因为在Promise结束之前可能有多个回调添加到它self.onRejectedCallback=[]//当Promisereject时设置的回调函数,因为可能添加了多个回调在Promise结束之前给它上面的executor(resolve,reject)//执行executor并传入相应的参数}Promise的结构简单来说就是有一个status表示三种状态,pending(暂停),resolve(完成)),并拒绝(rejected)。另外,它还有两个回调方法onResolvedCallback和onRejectedCallback,分别对应resolve(完成)和reject(拒绝)。如果之前面试官问你promise的概念和基本用法,而你跟我一样提到了ajax,面试官很可能会问ajax(毕竟也是前端应该掌握的基础知识之一)。根据我的经验,一线大厂的面试官这时候很可能会要求你用promise做一个ajax。一是看你对promises和ajax的掌握程度,二是看你的编码能力。1.1使用promise实现ajax){if(this.readyState!==4){return;}if(this.status===200){resolve(this.response);}else{reject(newError(this.statusText));}}constclient=newXMLHttpRequest();client.open(type,url);client.onreadystatechange=handler;client.responseType='json';client.setRequestHeader("Accept","application/json");client.send();})returnpromise;}return{ajax};})()调用方法:$.ajax("/posts.json").then(function(json){console.log('Contents:'+json);},function(error){console.error('错误',错误);});(2)手动实现一个Promise/A需要注意的几点:1.then方法会返回一个新的promise,所以then方法要写在原型链上。2、promise的返回值或者抛出的err都会被传递。例如:newPromise(resolve=>resolve(8)).then().catch().then(function(value){alert(value)})//根据promise的定义和调用方式,promise可以先写函数Promise(executor){const_this=this;_this.status='pending';_ths.data=undefined;_this.onRejectedCallback=[];_this.onResolvedCallback=[];functionresolve(value){if(_this.status==='pending'){_this.status='resolved';_this.data=value;for(leti=0;i<_this.onResolvedCallback.length;i++){_this.onResolvedCallback[i](值);}}}函数拒绝(原因){if(_this.status==='pending'){_this.status='rejected';_this.data=reason;for(leti=0;i<_this.onResolvedCallback.length;i++){_this.onRejectedCallback[i](reason);}}}try{executor(resolve,reject);}catch(e){reject(e)}}//then方法应该写在原型链中Promise.prototype.then=function(onResolved,onRejected){constself=this;//判断onResolved和onRejected是否是方法onResolved=typeofonResolved==='函数'?onResolved:function(value){返回值}onRejected=typeofonRejected==='函数'?onRejected:function(reason){returnreason}if(self.status==='resolved'){returnnewPromise(function(resolve,reject){try{constresult=onResolved([self.data](https://link.zhihu.com/?target=http%3A//self.data));if(resultinstanceofPromise){//如果返回的是一个新的promise,那么使用这个promise讨厌的方法resoult.then(resolve,reject)}resolve(result)//否则直接将返回值作为newPromise的result}.catch(e){reject(e);}});}//这里和之前的逻辑是一样的一个if块的of几乎是一样的,不同的是调用了onRejected函数,所以不用过多解释if(self.status==='rejected'){returnnewPromise(function(resolve,reject){try{varresult=onRejected([self.data](https://link.zhihu.com/?target=http%3A//self.data))if(resultinstanceofPromise){resoult.then(resolve,reject)}}catch(e){reject(e)}})}if(self.status==='pending'){returnnewPromise(function(){});}if(self.status==='悬而未决g'){//如果当前Promise还处于pending状态,我们不确定是调用onResolved还是onRejected,//只能等到Promise的状态被确认后才能真正处理//所以我们需要把我们的**两种情况**的处理逻辑作为回调放到promise1的回调数组中(这里是this/self)//逻辑本身和第一个if块中的差不多,不要这里解释太多returnPromise(function(resolve,reject){self.onResolvedCallback.push(function(value){try{varx=onResolved([self.data](https://link.zhihu.com/?target=http%3A//self.data))if(xinstanceofPromise){x.then(resolve,reject)}}catch(e){reject(e)}})self.onRejectedCallback.push(函数(原因){try{varx=onRejected([self.data](https://link.zhihu.com/?target=http%3A//self.data))if(xinstanceofPromise){x.then(resolve,reject)}}catch(e){reject(e)}})})}}(3)promise的使用应该避免哪些陷阱?面试时,如果能回答可能使用promise会出现哪些坑,如何避免。相信能给面试官一个好印象,尤其是面试2年工作经验的职位时。通过这些,可以很好的与培训班毕业的假简历区分开来。而这些注意点也是我在项目中实际踩过的坑。注意第1点,不要为了美化代码而刻意避免使用嵌套结构。在很多关于promises的科普教程中,作者都??会强调,对于代码的间接性,尽量不要使用嵌套结构。在ES7中,asyncawait语法就是专门用来处理这个事情的。但很多新手,在没有充分了解业务的情况下,一味地美化代码,避免“回调地狱”,往往会出大问题。1.1promis.all的坑想象一个场景,比如我们写的一个表单组件。如下图所示:共有三个选项组件,每个组件对应一个字典。当时组里一个实习生为了简化和美化代码,在这样一个组件中使用了Promise.all()。类似这样:fetchData1=function(){//请求组件1的字典};fetchData2=function(){//请求组件2的字典};fetchData3=function(){//请求组件3的字典};承诺.all([fetchData1,fetchData2,fetchData3]);当时看这段代码,没发现什么问题。结果到了生产环境,问题就出来了。控件1获取不到字典项,但是获取到组件1的字典接口就好了。最后只好重新阅读组件的源码才发现问题所在。原理是control2的接口有问题,导致整个Promise.all请求出错。所以在使用promise.all的时候要注意:对于与业务没有必然联系的请求,比如联动组件,不要使用promise.all。2、回调地狱不可怕,不要盲目使用asyncawait下面是一段比较常见的前端代码:asycn()=>{await获取订单1的数据;awaittogetthedataoforder2;...}when当订单2的数据与订单1的数据不直接相互依赖时,订单2的执行时间是订单1的两倍。在同一个方式,如果后面有订单3和4,将浪费更多时间。这也是导致前端页面卡顿的主要原因。面对如此常见的试题类型,我觉得还是要认真对待,因为如果只是在面试中死记硬背答案,很可能会失败。如果面试官看到你在背答案,他只需要问所有相关的知识点,或者让你手动实现,或者问你在项目中遇到了哪些陷阱,你是如何处理的。面试准备不充分的候选人会一下子露出马脚。因此,小编为大家准备了前端面试题材。之前小编将前端面试题的知识点整理成了PDF文档,方便大家查阅学习。现在,我免费分享给大家。小编新建了一个前端学习圈。欢迎大家加入学聊~希望大家在其中有所收获,聊得愉快!小伙伴们,点此进群游玩,获取资讯!最近跟小伙伴聊天,了解到Vue的面试题比较多。小编将Vue相关的面试资料分享给大家。点击此处免费获取!篇幅有限,小编还没展示完呢。如果需要文中全部资料,点击获取来源:前端面试题资料。祝大家在生活中都能找到自己的事业!