上一篇慕课css面试题,链接地址
下一篇慕课JS面试题,链接地址
1. js面试题
1. event loop事件循环机制
案例
- console.log(‘Hi‘)先在 2.Call Stack中执行, 执行完清空,再走1.Browser console。输出 Hi
- setTimeout ( function cb1() ) ;先在 2.Call Stack中执行,进入 3.Web APIs,在此停留5s。
- 并清除掉 2.Call Stack中的 setTimeout cb1。这里就执行结束了。
- 往下执行console.log(‘Bye’)
-console.log('Bye‘)先在 2.Call Stack中执行, 执行完清空,再走 1.Browser console。输出 Bye
- 到 Bye输出完,可执行代码全部执行完毕,2.Call Stack清空。此时 Timer cb1 还在 3.Web APIs中 5s还没到。
- 此时启动Event loop 机制,同步代码执行完毕,2.Call Stack 空了。
解释:暂时没有代码可被推入Call Stack中,会立即启动Event loop机制,浏览器内核启动的事件循环机制。此时Event loop 会一遍一遍从(异步回调)Callback Queue中找,有没有函数了,有函数就拿过来。拿过来就推入 Call Stack中执行。
- 一直等到 3,Web Apis中 Timer cb1定时器结束,推入4.Callback Queue中,并清除Web Apis的 Timer cb1。
- 此时Event loop 发现 回调队列 Queue中有一个可执行函数,并推入 2.Call Stack中,Queue清除掉 cb1函数。
- Call Stack中 现有 cb1函数,执行里面的 log.(‘cb1’) 并推入1.Browser console,控制台打印 cb1。并清除Call Stack中的log('cb1‘)
- Call Stack 会在从cb1函数中寻找可执行的log,此时cb1函数中无任何可执行内容,清除掉cb1函数方法。
到此为止,整段代码执行完毕
浏览器控制台输出
Hi Bye cb1
2.Promise面试题
1.promise 的三种状态是什么?状态和变化
案例
2.then和cath改变状态
3. 请解答以下promise面试题
3. 手写promise 加载图片
4. async/await 和 promise的关系?
- 案例
- 看如下题
const c 上 await如果要捕获错误可以使用 try catch捕获
5. 异步本质 ,看如下async/await顺序题?
- 答案
3. 讲解宏任务 macroTask 和微任务 microTask ?
- 案例
4.手写Promise 函数,内容有点多
./MyPromise.js文件
class MyPromise {
// 状态 [等待 实现了 拒绝了]
state = 'pending' // 状态, 'pending' 'fulfilled' 'rejected'
value = undefined // 成功后的值
reason = undefined // 失败后的原因
// 如果 resolve成功状态.then(fn1,fn2) 其中一个会被立即执行
// 此时如果 p1.then(fn1,fn2) = pending状态.then(fn1,fn2)
// 这时就无法判断 fn1 和fn2那个先执行,就需要将如下俩函数,存储起来
resolveCallbacks = [] // pending 状态下,储存成功的回调
rejectCallbacks = [] // pending 状态下,储存失败的回调
// 构造函数
constructor(fn) {
// 成功
const resolveHandler = (value) => {
if (this.state === 'pending') {
this.state = 'fulfilled' // 修改 成功状态
this.value = value // 修改成功后的值
// 这里是用this.value ,value不会在闭包中,减少内存
// 执行函数 resolveCallback
this.resolveCallbacks.forEach(fn => fn(this.value))
}
}
// 失败
const rejectHandler = (reason) => {
if (this.state === 'pending') {
this.state = 'rejected' // 修改 失败状态
this, reason = reason // 修改失败后的值
this.rejectCallbacks.forEach(fn => fn(this.reason))
}
}
// try 中执行函数 ,catch中抛出错误,提升稳定性
try {
fn(resolveHandler, rejectHandler)
} catch (err) {
rejectHandler(err)
}
}
// .then 会有成功回调,和失败回调
// 当 pending 状态下,fn1 fn2 会被存储到 callbacks 中
// callbacks 中就是 resolveCallback 或 rejectCallbacks
then(fn1, fn2) {
// 成功
// 判断fn1 是否是一个函数,如果是返回它自己,如果不是给它一个函数,返回它自己
fn1 = typeof fn1 === 'function' ? fn1 : (v) => v
// 失败
fn2 = typeof fn2 === 'function' ? fn2 : (e) => e
// 判断状态
// 等待时
if (this.state === 'pending') {
// 当前状态是pending,无法判断,只能先存储起来
const p1 = new MyPromise((resolve, reject) => {
this.resolveCallbacks.push(() => {
try {
const newValue = fn1(this.value)
resolve(newValue) // p1.value 变成了新的promise 对象
} catch (err) {
reject(err)
}
})
this.rejectCallbacks.push(() => {
try {
const newReason = fn2(this.reason)
reject(newReason) // p1.reason 变成了新的promise 对象
} catch (err) {
reject(err)
}
})
})
return p1
}
// 成功
if (this.state === 'fulfilled') {
const p1 = new MyPromise((resolve, reject) => {
try {
const newValue = fn1(this.value)
resolve(newValue)
} catch (err) {
reject(err)
}
})
return p1
}
// 失败
if (this.state === 'rejected') {
const p1 = new MyPromise((resolve, reject) => {
try {
const newReason = fn2(this.reason)
reject(newReason) // 其实它是 赋值给 p1.reason
} catch (err) {
reject(err)
}
})
return p1
}
}
// .catch 只有 失败回调。就是 then 的一个语法糖,简单模式。
catch(fn) {
return this.then(null, fn)
}
}
执行结果
1. promise.all 会怎样执行?
- all代表全部。在这里promise需要全部都成功执行,再返回新的 promise,包含所有的输出结果。
<body>
<h1>MyPromise.all 会怎样执行</h1>
<script src="./MyPromise.js"></script>
<script>
const p1 = new MyPromise((resolve, reject) => {
// resolve(100) // 成功
// reject('错误信息...') // 失败
// 宏任务,异步回调
setTimeout(() => {
resolve(100)
}, 500)
})
const p2 = MyPromise.resolve(200)
const p3 = MyPromise.resolve(300)
const p4 = MyPromise.reject('错误信息...')
// 传入 promise 数组,等待所有的都 fulfilled 之后,
// 返回新 promise , 包含所有的结果
const p5 = MyPromise.all([p1, p2, p3])
p5.then(result => console.log('all result', result))
</script>
</body>
./MyPromise.js 文件中
MyPromise.all = function (promiseList = []) {
const p1 = new MyPromise((resolve, reject) => {
const result = [] // 存储 promiseList 所有的结果
const length = promiseList.length // 记录 promise数组长度
let resolvedCount = 0 // 用于计数
// forEach 中不可使用 index,因为index是同步的,forEach会立即执行完
promiseList.forEach(p => {
// promise 有可能是同步有可能是异步,有可能等待一两秒才执行
p.then(data => {
result.push(data)
// resolvedCount 必须在 then里面做++
// 坚决不能使用 index
resolvedCount++
if (resolvedCount === length) {
// 已经 遍历到了最后一个 promise
resolve(result)
}
}).catch(err => {
reject(err)
})
})
})
return p1
}
执行结果
2. promise.race 会怎样执行?
- race 就是赛跑的意思,看那个promise跑的快就先执行那个,后面的舍弃