hooks
hooks copied to clipboard
useRequest runAsync 和 run 可能存在竞态
https://stackblitz.com/edit/react-ts-pskjg5?file=App.tsx
通过 useUpdateEffect 状态变更执行 run,同时手动执行 runAsync,此时 runAsync 可能永远无法 resolve
我在你的例子上做了点修改:https://stackblitz.com/edit/react-ts-pbtzon?file=App.tsx 无法复现你说的情况,我猜你的 log 打印的有歧义,导致你理解错了? @LaamGinghong
@liuyib 还是使用我的原 demo,按照以下步骤必现:
- 点击左侧按钮进行 setNum(可以多点几次)
- 点击右侧按钮,此时会同时执行 setNum 和 runAsync
- 因为使用 useUpdateEffect 去处理 num 的副作用,num 变化时执行 run
我理解出现这个问题的原因应该是内部对请求进行合并,后面的 run 将第一次的 runAsync 取消了以确保请求回来的 data 一定是最后一次 run 执行回来的。
我认可这种行为,但我认为被合并的异步行为是否应该要 reject 掉或者 resolve 掉,目前 runAsync 是一直在 pending 的状态
你好 我按照你的步骤,再次尝试了你的 demo,还是 get 不到你说的点。
请问:你的 demo 怎么证明 请求合并后 runAsync 是一直在 pending 的状态?或者说请求合并后 resolve 没有被执行?没有 log 或者其他东西直接证明,只是能看到 console.log(num);
少输出了而已。
你用我改过的 demo 试试,我在 resolve()
上一行加了 log,不管怎么点 以及 请求合没合并,都得看到预期的 log 的
@liuyib
可以看到首先我点击了两次左侧的按钮,然后再点击右侧的按钮,圈起来的 console.log('after request')
并没有被执行
然后我们如果直接打印 runAsync,可以看到控制台的 Promise 显示的状态就是 pending
https://stackblitz.com/edit/react-ts-irlzn6?file=App.tsx @liuyib 这个例子就能够看到了,onSuccess 里面根本没有打印 async
@LaamGinghong 按照你的步骤复现了,确实存在这个现象,很感谢你的反馈。不过暂时还不确定是不是 bug,先执行 runAsync 再执行 run,就会使得 runAsync 一直 pending。让大佬看看 @crazylxr 见哥 有空看看这个
https://github.com/alibaba/hooks/blob/d5fd82c5886d781ef12d8ff176ed9d03038e089b/packages/hooks/src/useRequest/src/Fetch.ts#L83
假设servicePromise
是一个异步3秒的函数,3秒内暴击触发3次 runAsync
,因为是在异步后访问 this.count
,3次拿到的值都会是3,这就导致会有一次的 runAsync
走进
https://github.com/alibaba/hooks/blob/d5fd82c5886d781ef12d8ff176ed9d03038e089b/packages/hooks/src/useRequest/src/Fetch.ts#L85
而这个Promise
没有 resolve
,所以永远 pending
。是不是可以考虑在这里直接 Promise.resolve(res)
runAsync 没有 resolve我也遇到了 但是我无法100%复现 我就简简单单调用 一开始好好的 莫名就不行了
const promises = [runAsync('abc'), runAsync('def')];
console.log(promises);
await Promise.all(promises);
这个不能这样用吗?其中一个一直都是pending,Promise.all就没办法resolve
这个问题很蛋疼 找了好久问题才发 智慧触发最后一个的数据
连续执行多次runAsync
, 只会resolve
一次,其他的全部pending
了
if (currentCount !== this.count) {
// prevent run.then when request is canceled
return new Promise(() => {});
}
const promises = [runAsync('abc'), runAsync('def')]; console.log(promises); await Promise.all(promises);
这个不能这样用吗?其中一个一直都是pending,Promise.all就没办法resolve
使用 fetchKey 让useRequest并行,就可以用Promise.all 了
runAsync 没有 resolve我也遇到了 但是我无法100%复现 我就简简单单调用 一开始好好的 莫名就不行了
+1,我也遇到了,在上一个没结束时,发出另一个请求,有一个请求一直是pending,求问有解决方法吗
关联的 issue:https://github.com/alibaba/hooks/issues/2078
这个 issue 就先 close 了,用上面的 issue 跟进这个问题