|
| 1 | +import { Badge } from '@theme'; |
| 2 | + |
| 3 | +# Using WebWorker <Badge text="Performance" type="info" /> |
| 4 | + |
| 5 | +When `enableWorker: true` and `Worker` is available, layout computation runs in a WebWorker to reduce main-thread blocking. |
| 6 | + |
| 7 | +However, if you pass **function callbacks** in options (e.g. `(node) => ...`), Worker mode may throw errors like: |
| 8 | + |
| 9 | +```txt |
| 10 | +DataCloneError: Failed to execute 'postMessage' on 'Worker': function could not be cloned |
| 11 | +``` |
| 12 | + |
| 13 | +## Why it happens |
| 14 | + |
| 15 | +The library transfers `data/options` between the main thread and the Worker via structured clone. **Functions are not structured-cloneable**, so any function inside options can break the transfer. |
| 16 | + |
| 17 | +## How to fix |
| 18 | + |
| 19 | +### Option 1: Use `Expr` (string expressions) instead of callbacks |
| 20 | + |
| 21 | +`@antv/layout` supports `Expr` (powered by `@antv/expr`) for many numeric/size fields. If a field’s type includes `Expr`, you can pass a string expression instead of a function. |
| 22 | + |
| 23 | +Example (ForceLayout): |
| 24 | + |
| 25 | +```ts |
| 26 | +import { ForceLayout } from '@antv/layout'; |
| 27 | + |
| 28 | +const layout = new ForceLayout({ |
| 29 | + enableWorker: true, |
| 30 | + nodeStrength: 'node.data.strength ?? -30', |
| 31 | + edgeStrength: 'edge.data.weight ?? 0.1', |
| 32 | + nodeSize: 'node.data.size ?? 10', |
| 33 | +}); |
| 34 | + |
| 35 | +await layout.execute(data); |
| 36 | +``` |
| 37 | + |
| 38 | +Expression variable names depend on the field: |
| 39 | + |
| 40 | +- Node fields usually use `node` |
| 41 | +- Edge fields usually use `edge` |
| 42 | +- Combo fields usually use `combo` |
| 43 | + |
| 44 | +### Option 2: Pre-compute values into your data |
| 45 | + |
| 46 | +If you used to do: |
| 47 | + |
| 48 | +```ts |
| 49 | +nodeSize: (node) => node.data.size |
| 50 | +``` |
| 51 | + |
| 52 | +You can pre-fill `data.nodes[i].data.size` and then use `nodeSize: 'node.data.size'` (or rely on defaults). |
| 53 | + |
| 54 | +### Option 3: If you need callbacks, don’t enable Worker |
| 55 | + |
| 56 | +Some capabilities inherently require functions and cannot be passed into Workers: |
| 57 | + |
| 58 | +- `onTick`-style callbacks |
| 59 | +- `node` / `edge` mapping functions |
| 60 | +- Any custom logic without an `Expr` alternative |
| 61 | + |
| 62 | +In these cases, run the layout on the main thread by keeping `enableWorker` off. |
0 commit comments