看到一段代码, setTimeout(resolve, 0), 不是很明白用意?

2021-09-01 17:39:45 +08:00
 yazoox
const whenStable = async () =>
  await act(async () => {
    await new Promise((resolve) => setTimeout(resolve, 0));
  });

原帖地址: https://stackoverflow.com/questions/60137762/how-can-i-test-a-react-hooks-component-by-changing-usestate?rq=1 只有一个回复,回复里面的测试文件,里面用到了这个

不是很理解这个的用意。如果说需要延时,那为什么 setTimeout 的参数是 0? 还是说,作者只是举个例子?应该设为比如 500,etc.?

以及,这个貌似有 warning

Warning: The callback passed to ReactTestUtils.act(...) function must not return anything.
3025 次点击
所在节点    React
15 条回复
Puteulanus
2021-09-01 17:43:46 +08:00
setTimeout 0 不是精确的没有延迟,看这意思是想等待到下个 event loop ?
just1
2021-09-01 17:43:57 +08:00
类似于 nextTick
misdake
2021-09-01 17:46:37 +08:00
microtask 和 macrotask 的区别吧。promise 是 microtask 。setTimeout 是 macrotask,会在所有 promise 执行之后再执行。
感觉原因应该是:界面变动都是通过 microtask 来实现的,setTimeout 的函数一旦运行就说明已全部执行完毕。
towave
2021-09-01 17:56:03 +08:00
RexG
2021-09-01 18:09:01 +08:00
@just1 @misdake 说的都对,就是这个操作
eason1874
2021-09-01 18:14:28 +08:00
用途是防阻塞。

浏览器是按顺序处理事件的,setTimeout 回调事件排在页面普通 JavaScript 代码后面,所以比较占时间的 JavaScript 可以放到 setTimeout 里面,等页面渲染好再去执行,防止阻塞导致白屏什么的。

setTimeout 不是真正的定时任务,意思是最快在这个时间执行,慢的话,说不准。如果前面事件有阻塞一辈子,那一辈子也不会执行。
KouShuiYu
2021-09-01 18:15:52 +08:00
估计是确保 DOM 已经更新
violetlai
2021-09-01 19:39:41 +08:00
有些插件需要等 dom 更新 才搞这个
2i2Re2PLMaDnghL
2021-09-01 19:51:53 +08:00
我觉得取个名字清楚点
const nexttick = () => new Promise((resolve) => setTimeout(resolve, 0));

//...
await nexttick()
//...

至于你的 warning,则是来源于 act(async () => {}) 这部分。但理论上来说这段中确实不包含任何 return,是不是返回了一个 Promise<undefined> 的原因?
wanguorui123
2021-09-01 20:01:18 +08:00
添加到事件队列末尾下个周期调用
slime7
2021-09-01 20:39:38 +08:00
我去抄 vuetify 的水波纹代码时也见过这个用法,用在添加水波纹动画的进入 class 上,我当时猜测是需要先设置一个初始样式,再用这个方式设置需要变形到的样式,这样才能产生 css 的 transition
Taikyo
2021-09-01 22:40:43 +08:00
加入宏任务,只是为了不让它被立刻执行,可以在下一个 event loop 去执行。
xxz0315
2021-09-02 13:00:00 +08:00
相当下一帧的意思
yazoox
2021-09-02 20:03:16 +08:00
@2i2Re2PLMaDnghL
有没有办法修改一下,消除这个警告?就按当前的用途
2i2Re2PLMaDnghL
2021-09-03 13:08:04 +08:00
@yazoox 简单地
act(async()=>{...})
转化为
act(()=>{(async()=>{...})()})

但其实没有任何意义,是这个 warning 本身有问题。
我猜想这个 warning 的设置似乎是为了避免有人「想当然地」用 act callback 传递测试失败信号。
为了绕过一个过于宽泛的 warning 这么做不好,你应当修正 warning 的提供者。
看上去这个 warning 不是 react 提供的,在 react 代码中全文搜索 "must not return anything" 类似文字均在处理要求 effect 只能返回一个函数。

这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。

https://www.v2ex.com/t/799308

V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。

V2EX is a community of developers, designers and creative people.

© 2021 V2EX