Workercom делает веб -работники приятными. Workercom - это крошечная библиотека (1,1 КБ) , которая устраняет умственный барьер мышления о postMessage и скрывает тот факт, что вы работаете с работниками. Переписываемые и улучшенные проблемы общения от comlink
На более абстрактном уровне это реализация RPC для postMessage и ES6.
$ yarn add workercom
Comlink.proxy (Workercom найдет функции, передавая и увлажняет их)function , class , семейства Error , семьи TypedArray и других Браузеры без поддержки прокси ES6 могут использовать прокси-полифилл.
Размер : ~ 2,5k, ~ 1,2k gzip'd, ~ 1,1k brotli'd
На мобильных телефонах, особенно на мобильных телефонах низкого уровня, важно сохранить максимально холодный поток, чтобы он мог быстро реагировать на взаимодействие с пользователями и обеспечить опыт без брюк. Поток пользовательского интерфейса должен быть только для работы пользовательского интерфейса . Веб -работники - это веб -API, который позволяет запускать код в отдельном потоке. Чтобы общаться с другой веткой, веб -работники предлагают API postMessage . Вы можете отправлять объекты JavaScript в качестве сообщений, используя myWorker.postMessage(someObject) , запуская событие message внутри работника.
Workercom превращает этот API на основе сообщений в нечто более удобное для разработчиков, предоставляя реализацию RPC: значения из одного потока могут использоваться в другом потоке (и наоборот), как локальные значения.
main.js
import { wrap } from "workercom" ;
import Worker from "worker-loader!./worker.js" ;
async function init ( ) {
const worker = new Worker ( ) ;
// WebWorkers use `postMessage` and therefore work with Workercom.
const obj = wrap ( worker ) ;
alert ( `Counter: ${ await obj . counter } ` ) ;
await obj . inc ( ) ;
alert ( `Counter: ${ await obj . counter } ` ) ;
}
init ( ) ;Worker.js
import { expose } from "workercom" ;
const obj = {
counter : 0 ,
inc ( ) {
this . counter ++ ;
} ,
} ;
expose ( obj ) ;main.js
import { wrap } from "workercom" ;
import Worker from "worker-loader!./worker.js" ;
async function init ( ) {
const remoteFunction = wrap ( new Worker ( ) ) ;
await remoteFunction ( callback ( value ) {
alert ( `Result: ${ value } ` ) ;
} ) ;
}
init ( ) ;Worker.js
import { expose } from "workercom" ;
async function remoteFunction ( cb ) {
await cb ( "A string from a worker" ) ;
}
expose ( remoteFunction ) ;SharedWorker При использовании Workercom с SharedWorker вы должны:
port , экземпляр SharedWorker , при вызове Workercom.wrap .Workercom.expose в рамках onconnect вызова общего работника.Совет профессионала: вы можете получить доступ к Devtools для любого общего работника, работающего в настоящее время в Chrome, переходя на: Chrome: // oscover/#работники
main.js
import { wrap } from "workercom" ;
import SharedWorker from "worker-loader?worker=SharedWorker!./worker.js" ;
async function init ( ) {
const worker = new SharedWorker ( ) ;
/**
* SharedWorkers communicate via the `postMessage` function in their `port` property.
* Therefore you must use the SharedWorker's `port` property when calling `Workercom.wrap`.
*/
const obj = wrap ( worker . port ) ;
alert ( `Counter: ${ await obj . counter } ` ) ;
await obj . inc ( ) ;
alert ( `Counter: ${ await obj . counter } ` ) ;
}
init ( ) ;Worker.js
import { expose } from "workercom" ;
const obj = {
counter : 0 ,
inc ( ) {
this . counter ++ ;
} ,
} ;
/**
* When a connection is made into this shared worker, expose `obj`
* via the connection `port`.
*/
onconnect = function ( event ) {
const port = event . ports [ 0 ] ;
expose ( obj , port ) ;
} ;
// Single line alternative:
// onconnect = (e) => expose(obj, e.ports[0]); Workercom.wrap(endpoint) и Workercom.expose(value, endpoint?) Цель Corkercom - сделать открытые значения из одного потока, доступных в другом. expose value в endpoint , где endpoint представляет собой интерфейс, похожий на postMessage .
wrap другой конец канала сообщения и возвращает прокси. Прокси будет иметь все свойства и функции открытого значения, но доступ и призывы по своей природе являются асинхронными. Это означает, что функция, которая возвращает число, теперь вернет обещание для номера. Как правило: если вы используете прокси, await перед ним. Исключения будут пойманы и повторно отображаются с другой стороны.
Workercom.installTransfer(name, transferables) и Comlink.proxyПо умолчанию каждый параметр функции, возвращаемое значение и значение свойства объекта копируется в смысле структурированного клонирования. Структурированное клонирование можно рассматривать как о глубоком копировании, но имеет некоторые ограничения. Смотрите эту таблицу для деталей.
Если вы хотите, чтобы значение было передано, а не скопировано - при условии, что значение составляет или содержит Transferable - вы можете завершить значение в вызов installTransfer() и предоставить список передаваемых значений:
import { installTransfer } from "workercom" ;
installTransfer < ArrayBuffer , string > ( "arraybuffer" , {
canHandle : ( value ) => value instanceof ArrayBuffer ,
serialize : ( value ) => [ _arrayBufferToBase64 ( value ) , [ ] ] ,
deserialize : ( { raw } ) => _base64ToArrayBuffer ( raw ) ,
} ) ; Удален Comlink.proxy() . Это произойдет автоматически
// myProxy.onready = Comlink.proxy((data) => {
// /* ... */
// });
// * And now
myProxy . onready = ( data ) => {
/* ... */
}См. Больше передачи по умолчанию
Обычно вы хотите использовать Workercom, чтобы добавить слушателя событий, где источник события находится в другом потоке:
button . addEventListener ( "click" , myProxy . onClick . bind ( myProxy ) ) ; Хотя это не бросится сразу, onClick никогда не будет вызван. Это связано с тем, что Event не является ни структурированным клонируемым, ни переносимым. В качестве обходного пути, Workercom предлагает обработчики передачи.
Каждый параметр функции и возвращаемое значение придаются всем зарегистрированным обработчикам передачи. Если один из обработчиков событий сигнализирует о том, что он может обрабатывать значение, возвращая true из canHandle() , теперь он отвечает за сериализацию значения структурированным клонируемым данным и за то, что он оставляет за собой значение. Передаточный обработчик был настроен с обеих сторон канала сообщения. Вот пример обработчика передачи для событий:
installTransfer < Event , {
target : {
id : string ;
classList : string [ ]
}
} > ( "EVENT" , {
canHandle : ( obj ) => obj instanceof Event ,
serialize : ( ev ) => {
return [
{
target : {
id : ev . target . id ,
classList : [ ... ev . target . classList ] ,
} ,
} ,
[ ] ,
] ;
} ,
deserialize : ( obj ) => obj ,
} ) ; Обратите внимание, что этот конкретный обработчик передачи не создаст реального Event , а просто объект, у которого есть event.target.id и event.target.classList . Часто этого достаточно. Если нет, обработчик передачи может быть легко дополнен, чтобы предоставить все необходимые данные.
Поддержка преобразования по умолчанию для function , class , семейства Error , семейства TypedArray
Workercom.releaseProxy Каждый прокси, созданный Workercom, имеет метод [releaseProxy] . Призыв к нему отсоединит прокси и открытый объект из канала сообщений, что позволит собирать оба конца.
const proxy = wrap ( port ) ;
// ... use the proxy ...
proxy [ releaseProxy ] ( ) ;Workercom.createEndpoint Каждый прокси, созданный Workercom, имеет метод [createEndpoint] . Вызов его вернет новый MessagePort , который был подключен к тому же объекту, что и прокси, который был вызван [createEndpoint] .
const port = myProxy [ createEndpoint ] ( ) ;
const newProxy = wrap ( port ) ;Workercom.windowEndpoint(window, context = self, targetOrigin = "*") Windows и веб -работники имеют несколько разные варианты postMessage . Если вы хотите использовать Workercom для общения с iframe или другим окном, вам нужно обернуть его windowEndpoint() .
window - это окно, с которым следует общаться. context - это EventTarget , в котором могут быть получены сообщения из window (часто self ). targetOrigin передается в postMessage и позволяет фильтровать сообщения по происхождению. Для получения подробной информации см. Документацию для Window.postMessage .
Для примера использования взгляните на примеры не работающих в папке docs .
Workercom действительно предоставляет типовые типы. Когда вы expose() что -то из типа T , соответствующий вызов wrap() вернет что -то из типа Workercom.Remote<T> . Несмотря на то, что этот тип уже некоторое время проверялся в бою, он реализован на основе наилучшей экономии. Есть некоторые нюансы, которые невероятно сложны, если не невозможно правильно кодировать в системе типов типов. Иногда может быть необходимо заставить определенный тип, используя as unknown as <type> .
Workercom работает с модулем Node's worker_threads .
Лицензия MIT