Async Generators
Generators can be async to leverage Web Workers for heavy computations.
Creating Async Generators
app.generatorRegistry.register('asyncPattern', {
displayName: 'Async Pattern',
description: 'Pattern using Web Workers',
async: true, // Mark as async
params: {
minDistance: { type: 'number', default: 30 },
color: { type: 'color', default: '#8b5cf6' }
},
fn: async function(ctx) {
const { params, async: asyncHelpers, patternGroup, view } = ctx;
// Heavy computation in Worker
const points = await asyncHelpers.poissonDiskSampling(
view.size.width,
view.size.height,
params.minDistance
);
// Create visuals on main thread
points.forEach(pt => {
new paper.Path.Circle({
center: [pt.x, pt.y],
radius: 5,
fillColor: params.color,
parent: patternGroup
});
});
}
});
Executing Async Generators
await app.generatorRegistry.executeAsync('asyncPattern', {
minDistance: 40,
color: '#ef4444'
});
Async Context Helpers
Available in ctx.async:
| Method | Description |
|---|---|
poissonDiskSampling(w, h, dist) |
Even point distribution |
goldenRatioDistribution(count, w, h) |
Spiral distribution |
simplifyPath(points, tolerance) |
Reduce path points |
calculateGeneratorPositions(config) |
Generic position calc |
Example: Poisson Circles
app.generatorRegistry.register('poissonCircles', {
displayName: 'Poisson Circles',
async: true,
params: {
minDistance: { type: 'number', default: 50, min: 20, max: 100 },
minRadius: { type: 'number', default: 10 },
maxRadius: { type: 'number', default: 30 },
colors: { type: 'array', default: ['#3b82f6', '#8b5cf6', '#ec4899'] }
},
fn: async function(ctx) {
const { params, async: asyncHelpers, patternGroup, view } = ctx;
// Worker computation
const points = await asyncHelpers.poissonDiskSampling(
view.size.width,
view.size.height,
params.minDistance
);
// Main thread rendering
points.forEach((pt, i) => {
const radius = params.minRadius +
Math.random() * (params.maxRadius - params.minRadius);
const color = params.colors[i % params.colors.length];
new paper.Path.Circle({
center: [pt.x, pt.y],
radius: radius,
fillColor: color,
opacity: 0.7,
parent: patternGroup
});
});
}
});
Fallback Behavior
If Workers are unavailable, async helpers fall back to synchronous execution on the main thread.
// Check worker availability
if (ctx.async && app.workerPool.isAvailable()) {
// Use async
points = await ctx.async.poissonDiskSampling(w, h, dist);
} else {
// Fallback to sync
points = poissonDiskSampling(w, h, dist);
}
Performance Tips
- Use async generators for patterns with >100 elements
- Keep main-thread work (Paper.js) minimal
- Batch calculations in the worker when possible
- Consider progress indicators for long operations