Skip to content

面试记录

2024.06.19晚上八点,参与了远方大佬模拟面试,记录一下过程中的一些问题。

这里给大佬 引个流 ,特别感谢远方花费自己的时间给本人面试,给群友输出知识。

面试准备

  1. 需要对要面试的公司有一定的了解,防止冷场
  2. 需要对简历中写的东西负责,所有的细节一定要闭环
  3. 临场遇到准备以外的问题别怕,想好了闭环再有条不紊的回答,最差也就是没用过

面试吭哧瘪肚的问题

有几个突出的问题记录一下,查漏补缺!!!

ref解构

从所周知,vue3中基本上都是面向ref开发,通过ref定义的响应式变量在使用的时候需要带上.value,但是某些情况下他会自动解构其中的.value

模板语法1

ref是顶级变量的时候,这个时候可以直截了当。

vue
<template>
    <!-- 0 -->
    <div>{{ count }}</div>

    <!-- 1 -->
    <div>{{ count + 1 }}</div>
</template>
<script setup>
import { ref } from 'vue'
const count = ref(0)
</script>

模板语法2

ref是内部变量的时候,这个时候可以不了一点。

vue
<template>
    <!-- 0 -->
    <div>{{obj.val}}</div>

    <!-- [object Object]1 -->
    <div>{{ obj.val + 1 }}</div>
</template>
<script setup>
import { ref } from 'vue'
const obj = {
    val: ref(0)
}
</script>

因为obj.val实际上是一个ref对象,此时使用obj.val.value就可以了。

同理,const { val } = obj,这么玩也是会自动解构的,相当于模板语法1。

reactive

ref对象嵌套到另一个响应式对象的属性中时,访问属性会自动解包

vue
<template>
    <!-- 0 -->
    <div>{{obj.val}}</div>

    <!-- 1 -->
    <div>{{ obj.val + 1 }}</div>
</template>
<script setup>
import { ref, reactive } from 'vue'
const count = ref(0)
const obj = reactive({
  val: count
})
</script>

当然了,这里的reactive换成ref那就相当于直接定义了一个ref,自然也是一样ok的

新的ref?

如下文myRef写法会直接报错,而myRef2是正确的

ts
import { ref, Ref, UnwrapRef } from 'vue'
// 不能将类型“Ref<UnwrapRef<T>>”分配给类型“Ref<T>”。
// 不能将类型“UnwrapRef<T>”分配给类型“T”。
// const myRef = <T>(state: T): Ref<T> => {
//   return ref(state)
// }
const ref2Ref = <T>(state: T): Ref<UnwrapRef<T>> => {
  return ref(state)
}
const total = ref2Ref(count)

源码:

ts
export function ref<T>(value: T): Ref<UnwrapRef<T>>
export function ref<T = any>(): Ref<T | undefined>
export function ref(value?: unknown) {
  return createRef(value, false)
}

问题在于,泛型 T 可能是任何类型,包括但不限于基本类型、对象、数组,以及响应式引用。当你的函数声明返回 Ref<T> 时,你实际上是在承诺无论 T 是什么类型,返回的都将是 Ref<T> 类型。但是,如果 T 是一个响应式引用,ref(state) 将返回 Ref<UnwrapRef<T>>,这与 Ref<T> 不兼容

bff

Backend For Frontend(服务于前端的后端)。

鲁迅曾经说过:如果一个问题解决不掉,那么就加一个中间层,还解决不掉?再加一个中间层。

问题

有问题才有解决方案,他解决了什么呢?因为前端浏览器的上限是6个,而同一时间可能请求个数有茫茫多,暂定20个。

那么前面接口堵塞的时候,后面的接口就只能强行排队了。

这个时候就可以用node去实现一个bff,因为node请求后台服务绕过了浏览器这一层,没有并发限制,等到所有请求完成以后统一返回给web,就从另外一个层面解决了大量请求慢导致首页加载速度的问题。

Web Worker

既然提到了bff,自然就把Web Worker给带出来了,他是独立于 Web 应用程序主执行线程的后台线程中运行的脚本。

从定义上可以看出来,他只是协助解决js脚本单线程的问题的,而不是解决上述浏览器接口数目限制问题的。

应用场景:

  1. 复杂计算:图像处理、音频处理、视频处理等复杂的数据处理
  2. 后台下载:当需要下载大量数据时,可以使用 Web Worker 在后台进行数据的下载和处理,以避免阻塞用户界面
  3. 数据处理:当需要对大量数据进行处理或者排序时,可以使用 Web Worker 将处理逻辑放在后台线程中进行,提高处理的效率
  4. 实时通信:使用 Web Worker 来处理实时通信的逻辑。在主线程可以与 Web Worker 进行通信,从而实现实时的数据交换

面试题

填充以下代码使得满足以下要求:

  1. 只修改类Scheduler即满足异步请求的并发数控制
  2. addTask返回的是一个promise类型
  3. addTask以后每次执行的方法数目不得超过max
  4. stack中压栈的方法大于max个的时候,应该自动执行到空为止
js
// 最多同时执行n个异步任务
class Scheduler {
    constructor(max) {
        this.max = max || 2
        this.stack = []
    }
    addTask(asyncTask) {
        return new Promise((resolve, reject) => {
            
        })
    }
}

const scheduler = new Scheduler()

scheduler.addTask(() => {
    return new Promise((resolve) => {
        setTimeout(() => {
            resolve(1)
        }, 1000)
    })
}).then(console.log)

scheduler.addTask(() => {
    return new Promise((resolve) => {
        setTimeout(() => {
            resolve(2)
        }, 2000)
    })
}).then(console.log)

scheduler.addTask(() => {
    return new Promise((resolve) => {
        setTimeout(() => {
            resolve(3)
        }, 3000)
    })
}).then(console.log)
result
js
// 最多同时执行n个异步任务
class Scheduler {
    constructor(max) {
        this.max = max || 2
        this.stack = []
        this.runCount = 0
        this.map = new WeakMap()
    }
    run() {
        if (this.stack.length > 0 && this.runCount < this.max) {
            const asyncTask = this.stack.shift()
            this.runCount++
            const { resolve, reject } = this.map.get(asyncTask)
            asyncTask().then(resolve).catch(reject).finally(() => {
                this.runCount--
                this.run()
            })
        }
    }
    addTask(asyncTask) {
        return new Promise((resolve, reject) => {
            this.map.set(asyncTask, { resolve, reject })
            this.stack.push(asyncTask)
            this.run()
        })
    }
}

const scheduler = new Scheduler()

scheduler.addTask(() => {
    return new Promise((resolve) => {
        setTimeout(() => {
            resolve(1)
        }, 1000)
    })
}).then(console.log)

scheduler.addTask(() => {
    return new Promise((resolve) => {
        setTimeout(() => {
            resolve(2)
        }, 2000)
    })
}).then(console.log)

scheduler.addTask(() => {
    return new Promise((resolve) => {
        setTimeout(() => {
            resolve(3)
        }, 3000)
    })
}).then(console.log)

鄂ICP备2024055897号