Workercom은 웹 워크를 즐겁게 만듭니다. Workercom은 작은 도서관 (1.1KB) 으로, postMessage 에 대한 사고의 정신적 장벽을 제거하고 근로자와 함께 일하고 있다는 사실을 숨 깁니다. COMLINK에서 통신 문제를 다시 작성하고 개선했습니다
보다 추상적 인 수준에서는 postMessage 및 ES6 프록시를위한 RPC 구현입니다.
$ yarn add workercom
Comlink.proxy function (Workercom은 함수를 찾아 전송 및 수화합니다).function , class , Error 가족, TypedArray 가족 및 기타에 대한 기본 전환 지원 ES6 프록시 지원이없는 브라우저는 프록시 폴리 필을 사용할 수 있습니다.
크기 : ~ 2.5k, ~ 1.2k gzip'd, ~ 1.1k brotli'd
휴대 전화, 특히 저가형 휴대 전화에서는 메인 스레드를 가능한 한 유휴 상태로 유지하여 사용자 상호 작용에 빠르게 응답하고 jank없는 경험을 제공하는 것이 중요합니다. UI 스레드는 UI 작업에만 해당되어야합니다 . 웹 워커는 별도의 스레드에서 코드를 실행할 수있는 웹 API입니다. 다른 스레드와 의사 소통하기 위해 웹 워크는 postMessage API를 제공합니다. myWorker.postMessage(someObject) 를 사용하여 JavaScript 객체를 메시지로 보낼 수 있으며 작업자 내부에서 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 SharedWorker 와 함께 작업자를 사용하는 경우 다음을 수행해야합니다.
Workercom.wrap 호출 할 때 SharedWorker 인스턴스의 port 속성을 사용하십시오.Workercom.expose 공유 작업자의 onconnect 콜백 내에서 노출하십시오.Pro Tip : 현재 크롬에서 실행중인 공유 작업자의 DevTools에 액세스 할 수 있습니다. Chrome : // 작업자 검사/#근로자
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?) Workercom의 목표는 한 스레드에서 노출 된 값을 다른 스레드에서 사용할 수 있도록하는 것입니다. Endpoint는 endpoint 에서 value 노출 expose . 여기서 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은 전송 처리기를 제공합니다.
각 기능 매개 변수 및 반환 값은 등록 된 모든 전송 처리기에게 제공됩니다. 이벤트 핸들러 중 하나가 canHandle() 에서 true 반환하여 값을 처리 할 수 있다는 신호를 보낸 경우 이제 값을 구조화 가능한 클로닝 가능한 데이터로 직렬화하고 값을 사로화해야합니다. 메시지 채널의 양쪽 에 전송 핸들러가 설정되었습니다. 다음은 이벤트의 예제 전송 처리기입니다.
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와 Web Workers는 약간 다른 변형의 postMessage 을 가지고 있습니다. iframe 또는 다른 창과 통신하기 위해 Workercom을 사용하려면 windowEndpoint() 로 래핑해야합니다.
window 통신 해야하는 창입니다. context 는 window 에서 메시지를받을 수있는 EventTarget 입니다 (종종 self ). targetOrigin postMessage 로 전달되어 원산지별로 메시지를 필터링 할 수 있습니다. 자세한 내용은 Window.postMessage 의 문서를 참조하십시오.
사용 예제의 경우 docs 폴더의 비 작업자 예를 살펴보십시오.
Workercom은 TypeScript 유형을 제공합니다. type T 의 무언가를 expose() 때 해당 wrap() 호출은 type Workercom.Remote<T> 의 무언가를 반환합니다. 이 유형은 현재 시간에 걸쳐 전투 테스트를 거쳤지만 최상의 효과로 구현됩니다. TypeScript 유형 시스템에서 올바르게 인코딩하는 것은 불가능하지는 않지만 엄청나게 어려운 뉘앙스가 있습니다. 때때로 as unknown as <type> 특정 유형을 강제해야 할 수도 있습니다 .
Workercom은 Node의 worker_threads 모듈과 함께 작동합니다.
라이센스 MIT