1 try-catch捕获promise?

不能 try-catch 主要用于捕获异常,注意,这里的异常,是指同步函数的异常,如果 try 里面的异步方法出现了异常,此时catch 是无法捕获到异常的,原因是因为:当异步函数抛出异常时,对于宏任务而言,执行函数时已经将该函数推入栈【微任务队列?(不一定对)—by 墨绶】,此时并不在 try-catch 所在的栈,所以 try-catch 并不能捕获到错误。对于微任务而言,比如 promise,promise 的构造函数的异常只能被自带的 reject 也就是.catch 函数捕获到。 那为啥async/await可以捕获呢? async/await进行了封装,本质是同步的,同步可以被捕获到。 下面第二条链接的文章比较详细,但我看不懂… — by 墨绶

参考资料: https://blog.csdn.net/qq_42376204/article/details/108322958 https://blog.csdn.net/qq_42471343/article/details/123753664

2 多个await中有一个报错了怎么处理?错误能否用 try/catch 捕获,如何捕获

紧接上文,可以。 — by 墨绶

  1. /**
  2. * @author 墨绶
  3. */
  4. async function test() {
  5. try {
  6. const res = await [axios.get/fetch/promise]
  7. console.log(res)
  8. } catch (err) {
  9. console.log(err)
  10. }
  11. }

3 map和forEach要怎么跳出?

map

理论上无法正常跳出,目前我想到的只有throw error — by 墨绶


可以使用 return 中断当次循环,无法直接跳出循环。 如果想要终止循环一般只能使用 throw new Error()方式抛出错误强行终止,当然这种方法需要在 map 最外层套上 try…catch…捕获错误,想要中断一般不使用 map 和 forEach,用一下其他的方法比较的好:

  • Array.prototype.every()
  • Array.prototype.some()
  • Array.prototype.find()
  • Array.prototype.findIndex()

— by 墨卷

forEach

同上,不知道对不对,等人补充 与 map 类似 — by 墨绶

for…in

es6最新语法,可以使用break,return等中断操作 — by 墨绶

4 sort底层遍历方法

v8引擎源码:插入排序、快速排序 一般通过数组中位数值等进行判断衡量使用哪种会更好! 此处可拓展… — by 墨卷

5 find 底层排序方法

可以看下这篇文章,讲了数组诸多方法的底层实现:https://www.jianshu.com/p/4f6de394eef1 — by 墨卷

6 put 和 post 的区别

参考资料: https://www.zhihu.com/question/48482736

7 三个自定义hook

— by 墨绶

  1. import { useRef } from 'react'
  2. export default function useWillMount(fn) {
  3. const isWillMount = useRef(true)
  4. if (isWillMount.current) {
  5. fn()
  6. }
  7. isWillMount.current = false
  8. }
  1. export default function useWillUnMount(fn) {
  2. useEffect(() => {
  3. console.log('init')
  4. return () => {
  5. console.log('即将销毁')
  6. fn()
  7. }
  8. }, [])
  9. }

8 抢购demo相关

8.1 封装倒计时hook

— by 墨卷

  1. import { useEffect, SetStateAction, Dispatch } from 'react';
  2. type CountDown = (
  3. nowCount: number,
  4. setNowCount: Dispatch<SetStateAction<number>>
  5. ) => void;
  6. const useCountdown: CountDown = (nowCount, setNowCount) => {
  7. useEffect(() => {
  8. const timer = setTimeout(() => {
  9. setNowCount(nowCount - 1);
  10. }, 1000);
  11. if (nowCount === 0) {
  12. clearTimeout(timer);
  13. }
  14. return () => clearTimeout(timer);
  15. }, [nowCount, setNowCount]);
  16. };
  17. export default useCountdown;

8.2 校准因setTimeout造成的时间误差

— by 墨绶

非封装版!非封装版!非封装版!
思路:大概思路就是程序运行开始的时候,直接用useRef存一个开始时间,之后每次都判定一下与这个时间之间的误差,根据当前误差进行修改下次的interval时间。
效果image.png大概能在10ms之内
bug fix:setTime是异步函数,实际结果修改不会立即生效!!!

// 防止因为刷新而改变,用useRef
const start = useRef(new Date().getTime())

useEffect(() => {
  const timer = setInterval(() => {
    // 会造成误差的放在前面
    setTime(time - 1)

    // 计算误差并修改下次时间
    let offset: number =
      new Date().getTime() - start.current - 1000 * (10 - time)
    setNextTime(1000 - offset)
    // setNextTime(1000) // 用来对比效果,如果不使用offset,误差将越来越大

    // log test
    console.log('该轮误差:', offset)
    console.log('当前总时间:', new Date().getTime() - start.current)
  }, nextTime)

  if (time === 0) {
    setStatus(1)
    clearInterval(timer) // 清除最后一个定时器,结束useEffect
  }

  return () => {
    // 每次都清除当前timer,防止堆叠
    clearInterval(timer)
  }
}, [time])

8.3 css实现边框竖线

— by 升正

实现效果图如下:
image.png
思路
这个css布局唯一的难点在于中间的凹陷部分及虚线,所以整体布局需考虑这个因素。
如果是一个大的card来包裹,那么中间那个凹陷部分则需要在html中写四个div定位到那边来填空,个人认为css的样式应该尽可能的少牵扯到html中,也就是说html不要为了css构大量的构造一些无意义的标签。
所以说我的布局是这样的:
image.png
这里我被迫用了一个div来画那个线,具体原因后面会说明。
其中的细节布局不再强调,用flex和居中的一些知识即可完成。重点讲这个线和这个凹进去的东东。
四个凹槽
看起来像是两个,实际需要四个凹槽来组成这两个。加个边框看的更清楚一些
image.png
那要实现这四个边框,左边和右边需要拆开来写,也就是left和right需要是两个div不同的去写样式,而不是把样式都丢到一个card里面去。
然后再用到::before,::after伪元素来给他们添加这四个凹槽,凹槽也就是加border,需要用到定位,给它定位到那边拼凑起来。

.card-left {
  padding-right: 40px;
  position: relative;
  height: 200px;
  width: 500px;
  display: flex;
  align-items: center;
  padding-left: 20px;
  background-color: rgb(253, 247, 243);
  border-radius: 10px 0 0 10px;
}
.card-right {
  height: 200px;
  width: 200px;
  background-color: rgb(253, 247, 243);
  position: relative;
  display: flex;
  border-radius: 0 10px 10px 0;
}
/* 抽离公共样式 */
.card-right::before,
.card-right::after,
.card-left::before,
.card-left::after {
  content: '';
  width: 10px;
  height: 10px;
  border: 1px solid transparent;
  z-index: 1;
  background-color: #fff;
  position: absolute;
}
.card-right::before {
  top: 0px;
  left: -1px;
  border-radius: 0 0 10px 0;
}
.card-right::after {
  left: -1px;
  bottom: 0px;
  border-radius: 0 10px 0 0;
}
.card-left::before {
  right: -1px;
  top: 0px;
  border-radius: 0 0 0 10px;
}
.card-left::after {
  right: -1px;
  bottom: 0px;
  border-radius: 10px 0 0 0;
}

虚线
因为左右的before和after被用完了。。我这边就只能搞一个div来画线,不然混在一起太乱了。
具体代码:

.card-line {
  width: 2px;
  height: 180px;
  margin-top: 10px;
  background-color: rgb(253, 247, 243);
  background-image: linear-gradient(
    to bottom,
    #ccc 50%,
    transparent 50%
  );
  background-size: 2px 10px;
  background-repeat: repeat-y;
}

解析
首先设置宽高,肉眼预估宽度得2px,高度的计算是 = 卡片高度200 - 上下两个圆角102 = 180px。
再需要margin-top是因为这个线默认是顶部对齐的,所以需要往下移动10px,就margin-top:10px,让它距离顶部10px
然后是重点,其实需要实现这个斑马线的效果,就是一个灰色一个白色这样重复叠加的效果,所以说用到linear-gradient这个渐变,to bottom就是从上往下渐变,将整个内容分成100%, 前面50%是#ccc,后面又写了一个transparent 50%, 和前面的#ccc 的50% 的百分比一致,结果就是中间没有渐变的效果,从50%之前是#ccc,那50%就是一个分界线,50%之后全是transparent。就形成了一个打点的效果。
最后设置我们画的这个点的大小,background-size:第一个值设置宽度,第二个值设置的高度
最后一个就是设置这个画的重复,y轴上无限重复,直到高度为180px。
*缺陷

我这个应该不是标准答案,因为如果有注重细节的同学会发现,我没有画阴影。因为我分了左右布局,就导致了这个左边和右边的阴影画起来会很不自然。然后因为中间挖空用的是#fff,也就是白色的,会导致加了阴影的中间的空是一个白色的效果。所以说,只能参考一下,但是实际还是有缺陷,但是那个虚线点,我这么画没问题!

8.4 实现抢购结束此条1s后消失,其他券上移

.deleteCard {
  animation: drop 0.8s ease;
}

@keyframes drop {
  60% {
    height: 200px;
    margin: 10px 0;
    transform: translateX(800px);
    opacity: 0;
  }
  100% {
    margin: 0;
    transform: translateX(800px);
    opacity: 0;
    height: 0;
  }
}

9 不常用的css

// 悬浮、选中时的css修改
&:hover {
  background-color: #fff0e3;
  .item-right {
    .item-get {
      color: #ff6430;
    }
  }
}
// 水平居中的方式
left: 50%;
transform: translateX(-50%);