mainThreadFn

Registers a function as a main-thread script: it gets native elements directly and changes them without a change-detection pass. import { mainThreadFn } from '@blotch/angular-lynx';

Info

Template handlers such as (bindtap) already run on the main thread. Main-thread scripts explains when you need this API instead.

Usage

src/app/app.ts
import { Component } from '@angular/core';
import {
  LYNX_ELEMENTS,
  LynxMainThreadEvent,
  mainThreadFn,
  type MainThread,
} from '@blotch/angular-lynx';

const highlight = mainThreadFn((event: MainThread.TouchEvent) => {
  event.currentTarget.setStyleProperty('background-color', '#ff5722');
});

@Component({
  selector: 'app-root',
  imports: [LYNX_ELEMENTS, LynxMainThreadEvent],
  template: `
    <view [mainThreadBindtap]="highlight">
      <text>Tap me</text>
    </view>
  `,
})
export class App {
  readonly highlight = highlight;
}

Bind the result with a LynxMainThreadEvent input, or call it with LynxMainThread.runOnMainThread().

API

mainThreadFn(fn)

function mainThreadFn<TArgs extends unknown[], TReturn>(
  fn: (...args: TArgs) => TReturn,
): MainThreadFnHandle<TArgs, TReturn>;
  • fn: the function to run on the main thread. As an event handler, it receives the event.
  • Returns a handle. The handle's type keeps fn's argument and return types, so runOnMainThread() checks them.

'main thread' directive

const highlight = (event: MainThread.TouchEvent) => {
  'main thread';
  event.currentTarget.setStyleProperty('background-color', '#ff5722');
};

The build wraps any function whose first statement is 'main thread' (or 'main-thread') in mainThreadFn(), and adds the import. The result is the same as calling mainThreadFn() yourself.

  • Arrow functions and function expressions with a block body are transformed, wherever they appear.
  • Function declarations and class methods aren't. Write const name = () => { 'main thread'; … } instead.

Constraints

  • Define it at module scope. Both copies of your app then give it the same ID, which a call from the background thread needs. A class property also works for a [mainThreadBind*] input, but each new instance registers another function that's never released.
  • It runs in the main-thread copy of your module. Module-level variables it reads are that copy's, not the background thread's.
  • Keep state between calls in a MainThreadRef.
  • Arguments and return values from the background thread are copied as JSON.

Types

// An opaque handle. Its fields are internal.
type MainThreadFnHandle<
  TArgs extends unknown[] = unknown[],
  TReturn = unknown,
> = {
  /* internal */
};

MainThread.TouchEvent and the other event types are on LynxMainThreadEvent.