Movatterモバイル変換


[0]ホーム

URL:


Skip to content

Navigation Menu

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up

A JS communication port that can pass messages synchronously across workers

License

NotificationsYou must be signed in to change notification settings

sass/sync-message-port

Repository files navigation

This package exposes a utility class that encapsulates the ability to send andreceive messages with arbitrary structure across Node.js worker boundaries. Itcan be used as the building block for synchronous versions of APIs that aretraditionally only available asynchronously in the Node.js ecosystem by runningthe asynchronous APIs in a worker and accessing their results synchronously fromthe main thread.

Seethesync-child-process package for an example ofsync-message-port inaction.

API Docs

Usage

  1. UseSyncMessagePort.createChannel() to create a message channel that'sset up to be compatible withSyncMessagePorts. A normalMessageChannelwon't work!

  2. You can send thisMessageChannel's ports across worker boundaries just likeany otherMessagePort. Send one to the worker you want to communicate withsynchronously.

  3. Once you're ready to start sending and receiving messages, wrapboth portsinnew SyncMessagePort(), even if one is only ever going to be sendingmessages and not receiving them.

  4. UseSyncMessagePort.postMessage() to send messages andSyncMessagePort.receiveMessage() to receive them synchronously.

import{Worker}from'node:worker_threads';import{SyncMessagePort}from'sync-message-port';// or// const {SyncMessagePort} = require('sync-message-port');// Channels must be created using this function. A MessageChannel created by// hand won't work.constchannel=SyncMessagePort.createChannel();constlocalPort=newSyncMessagePort(channel.port1);constworker=newWorker(`  import {workerData} from 'node:worker_threads';  import {SyncMessagePort} from 'sync-message-port';  const remotePort = new SyncMessagePort(workerData.port);  setTimeout(() => {    remotePort.postMessage("hello from worker!");  }, 2000);`,{workerData:{port:channel.port2},transferList:[channel.port2],eval:true,});// Note that because workers report errors asynchronously, this won't report an// error if the worker fails to load because the main thread will be// synchronously waiting for its first message.worker.on('error',console.error);console.log(localPort.receiveMessage());

Why synchrony?

Although JavaScript in general and Node.js in particular are typically designedto embrace asynchrony, there are a number of reasons why a synchronous API maybe preferable or even necessary.

No a/synchronous polymorphism

Althoughasync/await and thePromise API has substantially improved theusability of writing asynchronous code in JavaScript, it doesn't address onecore issue: there's no way to write code that'spolymorphic over asynchrony.Put in simpler terms, there's no language-level way to write a complex functionthat takes a callback and to run that functions synchronously if the callback issynchronous and asynchronously otherwise. The only option is to write thefunction twice.

This poses a real, practical problem when interacting with libraries. Supposeyou have a library that takes a callback option—for example, an HTMLsanitization library that takes a callback to determine how to handle a given<a href="...">. The library doesn't need to do any IO itself, so it's writtensynchronously. But what if your callback wants to make an HTTP request todetermine how to handle a tag? You're stuck unless you can make that requestsynchronous. This library makes that possible.

Performance considerations

Asynchrony is generally more performant in situations where there's a largeamount of concurrent IO happening. But when performance is CPU-bound, it's oftensubstantially worse due to the overhead of bouncing back and forth between theevent loop and user code.

As a real-world example, the Sass compiler API supports both synchronous andasynchronous code paths to work around the polymorphism problem described above.The logic of these paths is exactly the same—the only difference is that theasynchronous path's functions all returnPromises instead of synchronousvalues. Compiling with the asynchronous path often takes 2-3x longer than withthe synchronous path. This means that being able to run plugins synchronouslycan provide a substantial overall performance gain, even if the pluginsthemselves lose the benefit of concurrency.

How does it work?

This usesAtomics andSharedArrayBuffer under the covers to signalacross threads when messages are available, andworker_threads.receiveMessageOnPort() to actually retrieve messages.

Can I use this in a browser?

Unfortunately, no. Browsers don't support any equivalent ofworker_threads.receiveMessageOnPort(), even within worker threads. You couldmake a similar package that can transmit only binary data (or data that can beencoded as binary) using onlySharedArrayBuffer, but that's outside the scopeof this package.

Disclaimer: this is not an official Google product.

About

A JS communication port that can pass messages synchronously across workers

Resources

License

Code of conduct

Stars

Watchers

Forks

Packages

No packages published

[8]ページ先頭

©2009-2025 Movatter.jp