[🐞] Running multiple action$ simultaneously only runs one
Which component is affected?
Qwik City (routing)
Describe the bug
Doing:
Trying to run() multiple actions when a button is clicked.
<button onClick$={() => {
foo.run();
bar.run();
}}>Foo Bar</button>
Expect: These actions have run.
Happened: Randomly selected only one action has run.
Reproduction
https://github.com/genki/qwik-test/tree/no_multi_actions
Steps to reproduce
git clone the the above and npm run dev
The reproduction code is in src/router/index.tsx
Please note this expects the latest qwik is located ~/project/clone/qwik
System Info
System:
OS: macOS 13.1
CPU: (8) arm64 Apple M2
Memory: 84.31 MB / 24.00 GB
Shell: 3.5.1 - /opt/homebrew/bin/fish
Binaries:
Node: 19.7.0 - /opt/homebrew/bin/node
Yarn: 1.22.19 - /opt/homebrew/bin/yarn
npm: 9.5.0 - /opt/homebrew/bin/npm
Browsers:
Chrome: 110.0.5481.177
Firefox: 110.0.1
Safari: 16.2
npmPackages:
@builder.io/qwik: file:~/project/clone/qwik/packages/qwik => 0.21.0
@builder.io/qwik-city: file:~/project/clone/qwik/packages/qwik-city => 0.5.3
undici: ^5.20.0 => 5.20.0
vite: 4.0.4 => 4.0.4
Additional Information
I faced this issue as well at other situation such that several actions run at the same timing.
For example, when one signal triggers several useTask$ at once and each of them runs different actions.
Here's workaround I found for this issue:
Define the function that serializes execution of actions.
let prevAction = Promise.resolve();
export const enqueueAction = async (action, ...args) => {
await prevAction;
return prevAction = action.run(...args);
};
Then call it instead of run(...) like this:
// foo.run(args)
// bar.run(args)
enqueuAction(foo, args)
enqueuAction(bar, args)
man, I was going nuts with this issue
anyway, this solution seemed to work for me
useVisibleTask$(async () => {
await firstAction.submit({ data });
await secondAction.submit({ data });
});
which is kinda simpler
man, I was going nuts with this issue
anyway, this solution seemed to work for me
useVisibleTask$(async () => { await firstAction.submit({ data }); await secondAction.submit({ data }); });which is kinda simpler
I think this is a simple and elegant solution. Thanks @AleksKislov for sharing.
man, I was going nuts with this issue
anyway, this solution seemed to work for me
useVisibleTask$(async () => { await firstAction.submit({ data }); await secondAction.submit({ data }); });which is kinda simpler
But this is not "simultaneously", they are sequential.
I have no context about this discussion, tho.
But this is not "simultaneously", they are sequential.
well, yes, but at least it works for some cases.
But the thing that an action can interrupt other actions is a bummer
Hello team! I don't know if I understood this issue correctly, but I just created this stackblitz https://stackblitz.com/edit/qwik-starter-gckxmmvh?file=src/routes/index.tsx,src/routes/layout.tsx with this example, and it works!
Just let me know I'm wrong @genki @gioboa
Thanks!
I tested with Qwik v2 and this is still an issue.
In the console I can see only the log bar and not both as expected.
import { component$ } from "@qwik.dev/core";
import { globalAction$ } from "@qwik.dev/router";
export const useAction1 = globalAction$(() => {
console.log('foo');
});
export const useAction2 = globalAction$(() => {
console.log('bar');
});
export default component$(() => {
const action1 = useAction1();
const action2 = useAction2();
return (
<div>
<button onClick$={() => {
action1.submit();
action2.submit();
}}>Foo Bar</button>
</div>
);
});
@Varixo do you think our routeloader changes might help here?