Introducing figma-await-ipc: A simple await-able replacement for postMessage() cross-thread communication

In a Figma plugin, the code that has access to the document API and the code that renders the UI are in different contexts, so you need to use postMessage() to send a request for data from one thread to the other. The other thread then needs to listen for the "message" event and respond by calling postMessage() to send back the requested data. The source thread then also needs to listen for the "message" event to receive the requested data.

All of this asynchronous event handling is an awkward fit for what is conceptually a synchronous function call. The figma-await-ipc package wraps this process with a simpler interface.

The package’s call() function lets you essentially call a named function in the other thread, while awaiting the promised result. Any parameters you pass to call() after the function name will be passed into the receiving function:

// main.ts
import { call } from "figma-await-ipc";

try {
  const title = await call("getProperty", "title");
  figma.currentPage.selection[0].characters = title;
} catch (error) {
  console.error("Error fetching name property:", error);
}

Of course, making a call from one thread won’t do anything if there’s nothing in the other thread to receive that call. So every call() to a particular name must be paired with a receive() in the other thread to provide a function that will respond to that name:

// ui.tsx
import { receive } from "figma-await-ipc";

const storedProperties = { ... };

receive("getProperty", (key) => {
  if (!(key in storedProperties)) {
    throw new Error(`Unsupported property: ${key}`);
  }

  return storedProperties[key];
});

Any number of call()/receive() pairs can exist within a plugin, and they can make calls in either direction: from the main thread to the UI thread, or vice versa.

Let me know if anyone has questions about the figma-await-ipc package, or suggestions for improvements. There’s more info in the readme as well.

3 Likes

I changed the package name to figma-await-ipc, which I hope is a little clearer on what it’s for (at least if you know what IPC means). The latest package is available here:

I originally created this functionality for the fwidgets UI toolkit that I recently published.

2 Likes

Epic stuff! Thanks for sharing!

1 Like