stackblitz/alien-signals

Feature Request: tick() (and batch()?)

Closed this issue ยท 2 comments

Hi, thanks for implementing untrack(), I have come back with 2 more feature requests ๐Ÿ˜…

I would love to be able to use tick() and batch(), tick() waiting for any effects or computed to run.

My use case: I'm building a draggable library, and it will have a plugin system. Each plugin will be exactly like Vue Composition API, only using signals from alien-signals. The internal API right now(sans-signals) is somewhat like this:

instance.ctx.delta.x = e.clientX - instance.ctx.initial.x - instance.ctx.offset.x;
instance.ctx.delta.y = e.clientY - instance.ctx.initial.y - instance.ctx.offset.y;

// Core proposes delta
instance.ctx.proposed.x = instance.ctx.delta.x;
instance.ctx.proposed.y = instance.ctx.delta.y;

// Run the plugins
const run_result = run_plugins(instance, 'drag', e);

if (run_result) flush_effects(instance);
else return clear_effects(instance);

// Whatever offset we have had till now since the draggable() was mounted, add proposals to it, as long as they're not null
instance.ctx.offset.x += instance.ctx.proposed.x ?? 0;
instance.ctx.offset.y += instance.ctx.proposed.y ?? 0;

Post signals, it will become:

instance.ctx.delta.set()

// Core proposes delta
instance.ctx.proposed.set()

instance.ctx.phase = 'drag';

await EffectsWithinPLuginsToRun();

untrack(() => {
  instance.ctx.offset.set(instance.ctx.proposed.x/y)
})

Here, the effects within plugins will run when delta and proposed change(They'll watch these two properties in their own effect()s, and call ctx.propose() with new deltas). Then we wait for effects to be done running and then update offset in a non-notifying manner with the new proposed.

So, here I have two concerns: delta and proposed updates should be batched. As in, setting both shouldn't trigger the effects twice. Maybe this library already does that, not sure. But if it doesn't, a batch helper would be really beneficial.

Secondly, await EffectsWithinPLuginsToRun() should be await tick() essentially, to wait for all plugins to be done running, and then move forward.

I would really appreciate a solution to these problems, if its feasible ๐Ÿ˜„

Keep up the great work!
Thanks

So, here I have two concerns: delta and proposed updates should be batched. As in, setting both shouldn't trigger the effects twice.

We have startBatch, endBatch to support this use case:

import { startBatch, endBatch } from 'alien-signals'

startBatch()
instance.ctx.delta.set()

// Core proposes delta
instance.ctx.proposed.set()
endBatch()

For tick, the effect is run synchronously as soon as the nearest set/endBatch is executed, so we have no asynchronous tasks to wait for.

Ohh cool, didn't know that. It's prolly not documented haha! Thanks!