Async Formula Functions
Use an async formula function when a mounted cell needs data from an application service. Calls are grid-local, case-insensitive, and must be the top-level formula call.
A complete service-backed function
Section titled “A complete service-backed function”import { FormulaPlugin } from '@revolist/revogrid-pro';
grid.plugins = [FormulaPlugin];grid.columns = [ { prop: 'sku', name: 'SKU' }, // A { prop: 'service', name: 'Service' }, // B { prop: 'price', name: 'Service price' }, // C];grid.formulaWorkbook = { sheetId: 'Orders', rowIdProp: 'id' };
const plugins = await grid.getPlugins();const formulas = plugins.find(plugin => plugin instanceof FormulaPlugin);if (!formulas) throw new Error('FormulaPlugin is not mounted');
const disposeServicePrice = formulas.registerAsyncFormulaFunction({ name: 'SERVICEPRICE', async handler([sku, service], { signal, rawArgs }) { const response = await fetch( `/api/prices/${encodeURIComponent(String(sku))}?service=${encodeURIComponent(String(service))}`, { signal }, ); if (!response.ok) throw new Error(`Price request failed: ${response.status}`); console.debug('Authored arguments:', rawArgs); return (await response.json()).price; },});
grid.source = [{ id: 'order-1', sku: 'B-200', service: 'priority', price: '=SERVICEPRICE(A1,B1)',}];
// For example, dispose when this page is torn down.window.addEventListener('pagehide', disposeServicePrice, { once: true });Expected result: C1 first renders the default #LOADING state, then the returned price. The handler receives evaluated values (B-200, priority); rawArgs retains A1 and B1.
Map service errors
Section titled “Map service errors”The default rejected value is #ERROR. Use mapError when users need a domain-specific state:
const dispose = formulas.registerAsyncFormulaFunction({ name: 'SERVICEPRICE', handler: async ([sku], { signal }) => loadPrice(String(sku), signal), mapError: error => error instanceof Error && error.message.includes('404') ? '#NOT_FOUND!' : '#SERVICE!',});Expected result: a missing SKU displays #NOT_FOUND!; other rejections display #SERVICE!. mapError takes precedence over errorValue.
Observe and refresh states
Section titled “Observe and refresh states”const onStateChange = (event: CustomEvent) => { const { name, rowId, status, value, error } = event.detail; console.log({ name, rowId, status, value, error });};grid.addEventListener('asyncformulastatechange', onStateChange);
// Abort and clear cached SERVICEPRICE cells, then recalculate them on render.formulas.invalidateAsyncFormulaFunction('SERVICEPRICE');
// Teardowngrid.removeEventListener('asyncformulastatechange', onStateChange);dispose();Expected result: a call emits pending, then resolved or rejected. Repeated renders of the same stable cell/formula/arguments share one request and cached result; invalidation causes a new request.
Cancellation behavior
Section titled “Cancellation behavior”The handler’s signal is aborted when its cell arguments or formula change, the function is invalidated/unregistered, or the plugin is destroyed. Pass that signal to fetch or your service client. A stale request’s later resolution is ignored.
async handler([sku], { signal }) { const response = await fetch(`/api/prices/${sku}`, { signal }); return (await response.json()).price;}Expected result: editing A1 from B-200 to A-100 aborts the B-200 request and starts one for A-100; only the current request can update the cell.
Advanced: override a built-in name
Section titled “Advanced: override a built-in name”Registering VLOOKUP intentionally shadows the synchronous built-in only for this mounted grid and only until its disposer runs. Other grids and calculateFormulaWorkbook retain the built-in implementation.
Async functions receive evaluated scalar arguments plus rawArgs. They cannot be nested inside another expression, and headless calculateFormulaWorkbook does not execute them. Load external service data before a backend calculation.
Next steps
Section titled “Next steps”Previous: Cross-sheet Formulas · Next: Backend Calculation and Persistence · Deeper reference: Formula API