Promise 高频面试题及详细答案(实战版)_第1页
Promise 高频面试题及详细答案(实战版)_第2页
Promise 高频面试题及详细答案(实战版)_第3页
Promise 高频面试题及详细答案(实战版)_第4页
Promise 高频面试题及详细答案(实战版)_第5页
已阅读5页,还剩4页未读, 继续免费阅读

下载本文档

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

文档简介

Promise高频面试题及详细答案(实战版)一、基础概念题1.说说你对Promise的理解,它是用来解决什么问题的?参考答案:Promise是ES6新增的一种异步编程解决方案,主要用来处理JS中的异步操作,比如接口请求、定时器、文件读写等。在Promise出现之前,我们处理异步主要用回调函数,一旦异步逻辑多了,就会出现多层回调嵌套,也就是常说的「回调地狱」,代码嵌套层级深、可读性极差、难以维护和调试。而Promise把异步操作从嵌套的回调写法,改成了链式调用的写法,让代码扁平化、逻辑更清晰,同时能统一管理异步成功和失败的状态,方便错误捕获。简单来说,核心作用就是:解决回调地狱、统一异步状态、支持链式调用、方便异常处理。2.Promise的三种状态分别是什么?有什么特点?参考答案:Promise一共有三种固定状态,且状态一旦改变就不可逆、不可二次修改。pending(等待中):初始状态,异步操作还没完成,既没有成功也没有失败fulfilled/resolved(已成功):异步操作执行成功,状态从pending变为resolvedrejected(已失败):异步操作执行失败,状态从pending变为rejected状态切换只有两种可能:pending=>resolved、pending=>rejected。一旦状态落地为成功或失败,后续再修改、再调用resolve/reject都不会生效。3.Promise中resolve和reject的作用是什么?参考答案:Promise构造函数的回调中会传入两个参数,都是函数:resolve():将Promise状态从pending改为resolved,同时把异步成功的结果值传递出去,供后面的.then方法接收reject():将Promise状态从pending改为rejected,同时把失败的原因、错误信息传递出去,供.catch或者then的第二个回调接收二、核心方法面试题4.说说then、catch、finally三个方法的用法和区别参考答案:1..then()专门处理Promise成功的回调,支持两个参数,第一个是成功回调,第二个是可选的失败回调。最重要的特点是支持链式调用,每次then执行完都会返回一个全新的Promise,所以可以一直链式写下去,解决回调嵌套问题。2..catch()专门捕获Promise的错误,包括reject抛出的错误、then内部代码报错、语法错误等。它可以捕获整条Promise链上的异常,一般写在链式调用的最后,做统一异常处理,比then的第二个回调更常用,因为可以集中兜底错误。3..finally()无论Promise最终成功还是失败,finally里的代码一定会执行。它不接收结果参数,也不会改变Promise的状态,常用于做收尾操作,比如关闭loading、终止加载状态、清除定时器等。5.Promise.all、Promise.race、Promise.allSettled、Promise.any的区别和使用场景参考答案:这四个方法都是用来批量处理多个Promise实例的,区别在于结束规则和返回结果不同。1.Promise.all()规则:全部成功才成功,一个失败就直接失败。接收一个Promise数组,只有所有Promise都resolved,才会返回所有结果的数组;只要有一个rejected,直接抛出第一个失败的错误。场景:多个接口必须全部请求成功才渲染页面,缺一不可的场景,比如页面初始化需要多个接口数据。2.Promise.race()规则:谁先结束就返回谁,无论成功失败。多个Promise竞争执行,最先完成(resolved/rejected)的那个结果,就是最终结果,其余Promise会继续执行但结果会被忽略。场景:接口超时拦截、请求竞速,比如接口请求5秒没返回就判定超时失败。3.Promise.allSettled()规则:所有Promise全部执行完毕,不管成功失败,统一返回结果。返回的结果数组中,每一项都会标注当前Promise的状态(fulfilled/rejected)和对应值,不会报错。场景:批量操作不要求全部成功,需要统计所有结果,比如批量上传文件、批量删除数据,需要知道哪些成功、哪些失败。4.Promise.any()规则:一个成功就成功,全部失败才失败。只要有一个Promise成功,就立刻返回成功结果;所有Promise都失败,才会抛出聚合错误。场景:多域名备用请求、多接口兜底,请求多个相同数据源,只要一个成功即可。三、异步执行顺序面试题(必考)6.讲讲Promise的执行顺序,宏任务和微任务的区别参考答案:JS执行机制是先执行同步代码,再执行微任务,最后执行宏任务。Promise的then、catch、finally属于微任务,优先级高于定时器、ajax、页面渲染这类宏任务。完整执行流程:执行所有同步代码清空所有微任务队列(Promise回调优先执行)执行一个宏任务再次清空微任务,再执行下一个宏任务,循环往复(事件循环)简单记:同步>微任务(Promise)>宏任务(setTimeout)。7.经典执行顺序代码题+解析题目:PlainText

console.log(1)

newPromise(resolve=>{

console.log(2)

resolve()

console.log(3)

}).then(()=>{

console.log(4)

})

setTimeout(()=>{

console.log(5)

},0)

console.log(6)答案输出:123645详细解析:同步代码打印1进入Promise构造函数内部,构造函数内部的代码是同步的,打印2执行resolve(),修改状态,但不会立即执行then回调,进入微任务队列继续同步执行打印3定时器是宏任务,放入宏任务队列同步代码打印6,所有同步执行完毕清空微任务队列,执行then回调,打印4执行宏任务,打印5四、手写源码面试题(中级必问)8.简单手写一个基础Promise(适配面试最简版)参考答案(可直接背):PlainText

classMyPromise{

constructor(executor){

//初始状态

this.status='pending'

//成功值、失败原因

this.value=undefined

this.reason=undefined

//存储回调(处理异步延迟场景)

this.onFulfilledCallbacks=[]

this.onRejectedCallbacks=[]

//成功处理

constresolve=(value)=>{

if(this.status==='pending'){

this.status='fulfilled'

this.value=value

//执行所有成功回调

this.onFulfilledCallbacks.forEach(fn=>fn())

}

}

//失败处理

constreject=(reason)=>{

if(this.status==='pending'){

this.status='rejected'

this.reason=reason

//执行所有失败回调

this.onRejectedCallbacks.forEach(fn=>fn())

}

}

//执行传入的函数,捕获异常

try{

executor(resolve,reject)

}catch(err){

reject(err)

}

}

//then方法

then(onFulfilled,onRejected){

//状态成功,直接执行回调

if(this.status==='fulfilled'){

onFulfilled(this.value)

}

//状态失败,执行失败回调

if(this.status==='rejected'){

onRejected(this.reason)

}

//异步场景,状态还在pending,缓存回调

if(this.status==='pending'){

this.onFulfilledCallbacks.push(()=>onFulfilled(this.value))

this.onRejectedCallbacks.push(()=>onRejected(this.reason))

}

}

}面试加分话术:我手写的Promise实现了核心逻辑,包含三种状态不可逆、resolve/reject状态修改、同步异步场景兼容、异常捕获和then回调缓存,满足日常异步使用的核心需求。9.手写Promise.all方法参考答案:PlainText

functionmyPromiseAll(promiseArr){

returnnewPromise((resolve,reject)=>{

letresult=[]

letcount=0

constlen=promiseArr.length

//空数组直接返回空

if(len===0){

resolve([])

return

}

//遍历执行所有promise

for(leti=0;i<len;i++){

Promise.resolve(promiseArr[i]).then(res=>{

result[i]=res

count++

//全部执行成功,返回结果数组

if(count===len){

resolve(result)

}

}).catch(err=>{

//一个失败直接失败

reject(err)

})

}

})

}五、高频细节坑点面试题10.Promise的then为什么可以链式调用?和链式调用jq有什么区别?参考答案:Promise的then、catch、finally每一次执行,都会返回一个全新的Promise实例,所以可以持续链式调用。和jq链式的区别:jq链式是返回自身this,操作的是同一个对象Promise链式是返回新实例,每一次链式都是全新的Promise,前后状态互不干扰11.Promise报错后,如果没有catch会怎么样?怎么避免?参考答案:Promise内部报错、reject触发失败后,如果没有catch捕获,会出现未捕获的Promise异常,控制台会报红报错,且不会终止代码执行,但会造成异常堆积、逻辑异常。避免方式:每条Promise链式调用最后统一加catch兜底使用async/await时,用try/catch包裹异步逻辑全局监听unhandledrejection事件统一捕获未处理异常12.async/await和Promise的关系是什么?参考答案:async/await是Promise的语法糖,本质还是基于Promise实现的,只是把Promise的链式异步写法,改成了同步顺序的写法,代码可读性更高。特点:async修饰的函数,返回值一定会包装成Promiseawait只能在async函数中使用,会阻塞后续代码,等待Promise状态落地优点:解决Promise链式过长的问题,逻辑更贴近同步代码;缺点:会阻塞代码,需要合理拆分六、实战场景题13.如何控制多个异步请求串行执行(依次执行)?参考答案:Promise.all是并行执行,如果需要串行依次执行,有两种常用方式:方式1:链式then嵌套PlainText

fn1().then(()=>fn2()).then(()

温馨提示

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

评论

0/150

提交评论