前言
小编之前写过一篇:前端面试之问到promise怎么办?,温故而知新哦
怎么明天又来一篇与promise的文章呢 ,哈哈哈哈小伙伴们不要急着来到哈,是因为意识了一个去找实习的同学,聊了实习找的怎么了,让我印象最粗浅的就是她讲promise的面试题,她说一面完结后就晓得凉凉了,并且要是有机会很想和面试官说一句:面试官对不起!我终于会了Promise!
大略是这么个状况,所以呀小编又来讲讲promise,前面带有面试题。同学加入的是某大厂面试,大家看看面试题及同学的答复就晓得这位同学有多好受了。
面试题
- CSS 实现程度垂直居中
- flex的属性
- CSS transition的实现成果和有哪些属性
- CSS 实现沿Y轴旋转360度 (间接自爆了 CSS不行....麻了)
- 好,那来点JS 根本数据类型有哪些 用什么判断
- 数组怎么判断
- 援用类型和根本类型的区别
- 什么是栈?什么是堆?
- 手写 翻转字符串
- 手写 Sum(1,2,3)的累加(argument)(我认为是柯里化,面试官笑了一下,脑筋不要这么死嘛)
- 箭头函数和一般函数的区别(上题遗记了argument,面试官特意问这个问题揭示我,奈何根底太差救不起来了...泪目)
- 数组去重的办法
- 图片懒加载
- 跨域产生的起因,同源策略是什么
- 说说你理解的解决办法(只说了JSONP和CORS)
- Cookie、sessionStorage、localStorage的区别
- get 和 post 的区别 (只说了传参形式和性能不同,面试官问还有吗 其余的不晓得了...)
- 问了一下我的项目,react
- 对ES6的理解 (Promise果然逃不了....)
- let var const的区别
- 晓得Promise嘛?聊聊对Promise的了解?(说了一下Promise对象代表一个异步操作,有三种状态,状态转变为单向...)
- 那它是为了解决什么问题的?(emmm当异步返回值又须要期待另一个异步就会嵌套回调,Promise能够解决这个回调天堂问题)
- 那它是如何解决回调天堂的?(Promise对象外部是同步的,外部失去外部值后进行调用.then的异步操作,能够始终.then .then ...)
- 好,你说能够始终.then .then ...那它是如何实现始终.then 的?(emmm... 这个.then链式调用就是...额这个...)
- Promise有哪些办法 all和race区别是什么
- 具体说一下 .catch() 和 reject (...我人麻了...)
完结环节
- 问了面试官对CSS的了解(必须但非重要,前端的外围还是尽量一比一还原设计稿,只有写好了页面能力思考交互)
- 如何学习(根底是最重要的,CSS和JS要重视实际,盖房子最重要的还是地基,所有的框架源码,组件等都基于CSS和JS)
- 已经是如何度过这个过程的(多做我的项目,在我的项目中学习了解每个细节,再次告诫我根底的重要性)
Promise概述
Promise是ES6新增的援用类型,能够通过new来进行实例化对象。Promise外部蕴含着异步的操作。
new Promise(fn)
Promise.resolve(fn)
这两种形式都会返回一个 Promise 对象。
- Promise 有三种状态: 期待态(Pending)、执行态(Fulfilled)和回绝态(Rejected),且Promise 必须为三种状态之一只有异步操作的后果,能够决定以后是哪一种状态,任何其余操作都无奈扭转这个状态。
- 状态只能由 Pending 变为 Fulfilled 或由 Pending 变为 Rejected ,且状态扭转之后不会在发生变化,会始终放弃这个状态。
- Pending 变为 Fulfilled 会失去一个公有value,Pending 变为 Rejected会失去一个公有reason,当Promise达到了Fulfilled或Rejected时,执行的异步代码会接管到这个value或reason。
晓得了这些,咱们能够失去上面的代码:
实现原理
class Promise { constructor() { this.state = 'pending' // 初始化 未实现状态 // 胜利的值 this.value = undefined; // 失败的起因 this.reason = undefined; }}复制代码
根本用法
Promise状态只能在外部进行操作,外部操作在Promise执行器函数执行。Promise必须承受一个函数作为参数,咱们称该函数为执行器函数,执行器函数又蕴含resolve和reject两个参数,它们是两个函数。
- resolve : 将Promise对象的状态从 Pending(进行中) 变为 Fulfilled(已胜利)
- reject : 将Promise对象的状态从 Pending(进行中) 变为 Rejected(已失败),并抛出谬误。
应用栗子
let p1 = new Promise((resolve,reject) => { resolve(value);})setTimeout(() => { console.log((p1)); // Promise {<fulfilled>: undefined}},1) let p2 = new Promise((resolve,reject) => { reject(reason);})setTimeout(() => { console.log((p2)); // Promise {<rejected>: undefined}},1) 复制代码
实现原理
- p1 resolve为胜利,接管参数value,状态扭转为fulfilled,不可再次扭转。
- p2 reject为失败,接管参数reason,状态扭转为rejected,不可再次扭转。
- 如果executor执行器函数执行报错,间接执行reject。
所以失去如下代码:
class Promise{ constructor(executor){ // 初始化state为期待态 this.state = 'pending'; // 胜利的值 this.value = undefined; // 失败的起因 this.reason = undefined; let resolve = value => { console.log(value); if (this.state === 'pending') { // resolve调用后,state转化为胜利态 console.log('fulfilled 状态被执行'); this.state = 'fulfilled'; // 贮存胜利的值 this.value = value; } }; let reject = reason => { console.log(reason); if (this.state === 'pending') { // reject调用后,state转化为失败态 console.log('rejected 状态被执行'); this.state = 'rejected'; // 贮存失败的起因 this.reason = reason; } }; // 如果 执行器函数 执行报错,间接执行reject try{ executor(resolve, reject); } catch (err) { reject(err); } } }复制代码
测验一下上述代码咯:
class Promise{...} // 上述代码new Promise((resolve, reject) => { console.log(0); setTimeout(() => { resolve(10) // 1 // reject('JS我不爱你了') // 2 // 可能有谬误 // throw new Error('是你的错') // 3 }, 1000)})复制代码
- 当执行代码1时输入为 0 后一秒输入 10 和 fulfilled 状态被执行;
- 当执行代码2时输入为 0 后一秒输入 我不爱你了 和 rejected 状态被执行
- 当执行代码3时 抛出谬误 是你的错
.then办法
promise.then(onFulfilled, onRejected)
- 初始化Promise时,执行器函数曾经扭转了Promise的状态。且执行器函数是同步执行的。异步操作返回的数据(胜利的值和失败的起因)能够交给.then解决,为Promise实例提供处理程序。
- Promise实例生成当前,能够用then办法别离指定resolved状态和rejected状态的回调函数。这两个函数onFulfilled,onRejected都是可选的,不肯定要提供。如果提供,则会Promise别离进入resolved状态和rejected状态时执行。
- 而且任何传给then办法的非函数类型参数都会被静默疏忽。
- then 办法必须返回一个新的 promise 对象(实现链式调用的要害)
实现原理
- Promise只能转换最终状态一次,所以onFulfilled和onRejected两个参数的操作是互斥的
- 当状态state为fulfilled,则执行onFulfilled,传入this.value。当状态state为rejected,则执行onRejected,传入this.reason
class Promise { constructor(executor) { this.state = 'pending' // 初始化 未实现状态 // 胜利的值 this.value = undefined; // 失败的起因 this.reason = undefined; // .then 立刻执行后 state为pengding 把.then保存起来 this.onResolvedCallbacks = []; this.onRejectedCallbacks = []; // 把异步工作 把后果交给 resolve let resolve = (value) => { if (this.state === 'pending') { console.log('fulfilled 状态被执行'); this.value = value this.state = 'fulfilled' // onFulfilled 要执行一次 this.onResolvedCallbacks.forEach(fn => fn()); } } let reject = (reason) => { if (this.state === 'pending') { console.log('rejected 状态被执行'); this.reason = reason this.state = 'rejected' this.onRejectedCallbacks.forEach(fn => fn()); } } try { executor(resolve, reject) } catch (e) { reject(err) } } // 一个promise解决了后(实现状态转移,把控制权交进去) then(onFulfilled, onRejected) { if (this.state == 'pending') { this.onResolvedCallbacks.push(() => { onFulfilled(this.value) }) this.onRejectedCallbacks.push(() => { onRejected(this.reason) }) } console.log('then'); // 状态为fulfilled 执行胜利 传入胜利后的回调 把执行权转移 if (this.state == 'fulfiiied') { onFulfilled(this.value); } // 状态为rejected 执行失败 传入失败后的回调 把执行权转移 if (this.state == 'rejected') { onRejected(this.reason) } }}let p1 = new Promise((resolve, reject) => { console.log(0); setTimeout(() => { // resolve(10) reject('JS我不爱你了') console.log('setTimeout'); }, 1000)}).then(null,(data) => { console.log(data, '++++++++++');})复制代码
0thenrejected 状态被执行JS我不爱你了 ++++++++++setTimeout复制代码
当resolve在setTomeout内执行,then时state还是pending期待状态 咱们就须要在then调用的时候,将胜利和失败存到各自的数组,一旦reject或者resolve,就调用它们。
现能够异步实现了,然而还是不能链式调用啊? 为保障 then 函数链式调用,then 须要返回 promise 实例,再把这个promise返回的值传入下一个then中。
Promise的各种办法
Promise.prototype.catch()
catch 异样处理函数,解决后面回调中可能抛出的异样。只接管一个参数onRejected处理程序。它相当于调用Promise.prototype.then(null,onRejected),所以它也会返回一个新的Promise
- 例如
let p = new Promise((resolve, reject) => { setTimeout(() => { resolve(10) }, 1000)}).then(() => { throw Error("1123")}).catch((err) => { console.log(err);}).then(() => { console.log('异样捕捉后能够持续.then');})复制代码
当第一个.then的异样被捕捉后能够继续执行。
Promise.all()
Promise.all()创立的Promise会在这一组Promise全副解决后在解决。也就是说会期待所有的promise程序都返回后果之后执行后续的程序。返回一个新的Promise。
- 例如
let p1 = new Promise((resolve, reject) => { resolve('success1')})let p2 = new Promise((resolve, reject) => { resolve('success1')})// let p3 = Promise.reject('failed3')Promise.all([p1, p2]).then((result) => { console.log(result) // ['success1', 'success2'] }).catch((error) => { console.log(error)})// Promise.all([p1,p3,p2]).then((result) => { // console.log(result)// }).catch((error) => { // console.log(error) // 'failed3' // // })复制代码
有上述例子失去,all的性质:
- 如果所有都胜利,则合成Promise的返回值就是所有子Promise的返回值数组。
- 如果有一个失败,那么第一个失败的会把本人的理由作为合成Promise的失败理由。
Promise.race()
Promise.race()是一组汇合中最先解决或最先回绝的Promise,返回一个新的Promise。
- 例如
let p1 = new Promise((resolve, reject) => { setTimeout(() => { resolve('success1') },1000)})let p2 = new Promise((resolve, reject) => { setTimeout(() => { reject('failed2') }, 1500)})Promise.race([p1, p2]).then((result) => { console.log(result)}).catch((error) => { console.log(error) // 'success1' })复制代码
有上述例子失去,race的性质:
- 无论如何,最先执行实现的,就执行相应前面的.then或者.catch。谁先以谁作为回调
小编总结的这份269页的大厂前端面试题材料,Promise相干的面试题也其中,小伙伴们请点击这里支付噢
总结
下面的Promise就总结到这里有什么了解也能够在下方评论区一起交流学习。
面试能够让本人发现更多的常识盲点,从而促成本人学习,大家一起加油冲呀!!
这篇文章小伙伴们也别忘了点赞+评论噢!!!