Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Implement ember concurrency examples #2

Draft
wants to merge 2 commits into
base: main
Choose a base branch
from

Conversation

BlueCutOfficial
Copy link
Collaborator

@BlueCutOfficial BlueCutOfficial commented Feb 23, 2024

Hey @paoloricciuti, these are just a few tests I've done to see what I could do with the lib, I left a few comments to discuss.
Also, it would be interesting to know if there are just different / easier ways to do this with Svelte.

@@ -52,7 +52,7 @@ export function task<TArgs = undefined, TReturn = unknown>(
cancel() {
abort_controller.abort();
},
perform(...args: undefined extends TArgs ? [] : [TArgs]) {
perform(...args: unknown[]) {
Copy link
Collaborator Author

@BlueCutOfficial BlueCutOfficial Feb 23, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I’ve been playing with svelte-concurrency and I encounter something a bit counter-intuitive with the task arguments. As it is on main, it seems that TArgs has to be an array. I didn’t follow all the threads about TypeScript constraints, but in the main page example, when you do:

const parent = task(async function* (param: number) {
   (...)
   return param * 2;
});

Let’s assume you think you have param === 4, you actually have param === [4] and do:

[4] * 2

Surprisingly it works because you can multiply values in arrays in JS, but in my "accelerating buttons" case I had 0 + [1] that resulted to a string "01".

...args: unknown[] is not a proposal, it's just my lazy fix to get it work =p

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ok this is actually something else: basically this TS code is inferring the type of TArgs. If you don't pass any parameter it will actually be undefined and when you call perfom this type will disallow you to pass any values. But if you pass some argument then the arguments will be the same arguments that you expect in the task function. It doesn't need to be an array, you can pass a single value and ts will infer that you want that kind of value and force you to use the same value in perform. So basically you can do this

const my_task = task((value: number)=>{
    console.log(value);
});

my_task.perform(4);

@@ -2,7 +2,7 @@ import { onDestroy } from 'svelte';
import { writable } from 'svelte/store';

type SvelteConcurrencyUtils = {
signal: AbortSignal;
abortController: AbortController;
Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I am not sure if I understand how signal is supposed to be used:

In my race case, I wanted a parent task that triggers 3 children tasks, and as soon as one of the children is done, everyone stops.

I couldn't figure out how / when onDestroy is supposed to be called, and I couldn't use cancel because it's kind of an "auto-cancellation", the parent task says in its own body "I am done, I stop all my children". I didn't see how to use the main branch's API to do that, I just wanted a way to run .abort() for the current function.

Considering everything you've already done in the task logic, what do you think is the cleanest way to achieve that?

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah we didn't implement that kind of concurrency yet. Probably i would just do something like

child.perform().then(()=>{
    child2.cancel();
    child3.cancel();
});
child2.perform().then(()=>{
    child.cancel();
    child3.cancel();
});
child3.perform().then(()=>{
    child.cancel();
    child2.cancel();
});

Comment on lines +52 to +58
<button
on:click={() => {
challengers[0].progress = 50;
challengers[1].progress = 20;
challengers[2].progress = 70;
}}
>Test</button>
Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I added this button to check the <progress> elements have their values updated on click, and that works. But my progress update in the different children's tasks has no effect, there might be something I need to learn about the render or for loop maybe?

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think you just need to call await tick(); after you update the value in the while loop.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants