@async/framework 0.7.0 → 0.8.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/src/signals.js CHANGED
@@ -96,7 +96,8 @@ export function computed(fn) {
96
96
  server: registry._context?.().server,
97
97
  router: registry._context?.().router,
98
98
  loader: registry._context?.().loader,
99
- cache: registry._context?.().cache
99
+ cache: registry._context?.().cache,
100
+ scheduler: registry._context?.().scheduler
100
101
  }));
101
102
  });
102
103
  }
@@ -124,6 +125,8 @@ export function createSignalRegistry(initialMap = {}, options = {}) {
124
125
  const registryCleanups = new Map();
125
126
  const runtimeContext = {};
126
127
  const boundEntries = new Set();
128
+ let subscriptionCounter = 0;
129
+ let effectCounter = 0;
127
130
 
128
131
  const registry = attachRegistryInspection({
129
132
  register(id, signalLike) {
@@ -199,17 +202,21 @@ export function createSignalRegistry(initialMap = {}, options = {}) {
199
202
  return createRef(registry, id);
200
203
  },
201
204
 
202
- subscribe(path, fn) {
205
+ subscribe(path, fn, options = {}) {
203
206
  if (typeof fn !== "function") {
204
207
  throw new TypeError("subscribe(path, fn) requires a function.");
205
208
  }
206
209
  const parsed = parsePath(path, entries);
207
210
  const entry = requireEntry(entries, parsed.id);
211
+ const subscriptionId = ++subscriptionCounter;
208
212
  return entry.subscribe(() => {
209
- fn(registry.get(parsed.path), {
213
+ scheduleCallback(() => fn(registry.get(parsed.path), {
210
214
  id: parsed.id,
211
215
  path: parsed.path,
212
216
  signal: entry
217
+ }), {
218
+ ...options,
219
+ key: options.key ?? `signal:${parsed.path}:${subscriptionId}`
213
220
  });
214
221
  });
215
222
  },
@@ -227,10 +234,12 @@ export function createSignalRegistry(initialMap = {}, options = {}) {
227
234
  return registry.ref(id);
228
235
  },
229
236
 
230
- effect(fn) {
237
+ effect(fn, options = {}) {
231
238
  let cleanup;
232
239
  let dependencyCleanups = [];
233
240
  let stopped = false;
241
+ const scheduler = options.scheduler;
242
+ const effectId = ++effectCounter;
234
243
 
235
244
  const run = () => {
236
245
  if (stopped) {
@@ -249,10 +258,22 @@ export function createSignalRegistry(initialMap = {}, options = {}) {
249
258
  server: runtimeContext.server,
250
259
  router: runtimeContext.router,
251
260
  loader: runtimeContext.loader,
252
- cache: runtimeContext.cache
261
+ cache: runtimeContext.cache,
262
+ scheduler: runtimeContext.scheduler
253
263
  }));
254
264
  cleanup = outcome.value;
255
- dependencyCleanups = outcome.dependencies.map((dependency) => registry.subscribe(dependency, run));
265
+ dependencyCleanups = outcome.dependencies.map((dependency) => registry.subscribe(dependency, scheduleRun));
266
+ };
267
+
268
+ const scheduleRun = () => {
269
+ if (!scheduler) {
270
+ run();
271
+ return;
272
+ }
273
+ scheduler.enqueue(options.phase ?? "effect", run, {
274
+ scope: options.scope,
275
+ key: options.key ?? `effect:${effectId}`
276
+ });
256
277
  };
257
278
 
258
279
  run();
@@ -329,6 +350,17 @@ export function createSignalRegistry(initialMap = {}, options = {}) {
329
350
  registryCleanups.set(id, cleanup);
330
351
  }
331
352
  }
353
+
354
+ function scheduleCallback(fn, options = {}) {
355
+ const scheduler = options.scheduler;
356
+ if (!scheduler || options.phase === "sync") {
357
+ return fn();
358
+ }
359
+ return scheduler.enqueue(options.phase ?? "effect", fn, {
360
+ scope: options.scope,
361
+ key: options.key
362
+ });
363
+ }
332
364
  }
333
365
 
334
366
  function normalizeSignal(signalLike) {