Workercom membuat pekerja web menyenangkan. WorkerCom adalah perpustakaan kecil (1.1kb) , yang menghilangkan penghalang mental pemikiran tentang postMessage dan menyembunyikan fakta bahwa Anda bekerja dengan pekerja. Menulis ulang dan meningkatkan masalah komunikasi dari Comlink
Pada tingkat yang lebih abstrak ini adalah implementasi RPC untuk proxy postMessage dan ES6.
$ yarn add workercom
Comlink.proxy yang tidak perlu (WorkerCom akan menemukan fungsi, mentransfer dan melembabkannya)function , class , Keluarga Error , Keluarga TypedArray dan Lainnya Browser tanpa dukungan proxy ES6 dapat menggunakan proxy-polyfill.
Ukuran : ~ 2.5k, ~ 1.2k gzip'd, ~ 1.1k brotli'd
Pada ponsel, dan terutama pada ponsel kelas bawah, penting untuk menjaga utas utama seakilah mungkin sehingga dapat merespons interaksi pengguna dengan cepat dan memberikan pengalaman bebas jank. Utas UI seharusnya hanya untuk pekerjaan UI . WebWorkers adalah API Web yang memungkinkan Anda menjalankan kode di utas terpisah. Untuk berkomunikasi dengan utas lain, WebWorkers menawarkan API postMessage . Anda dapat mengirim objek JavaScript sebagai pesan menggunakan myWorker.postMessage(someObject) , memicu peristiwa message di dalam pekerja.
WorkerCom mengubah API berbasis pesan ini menjadi sesuatu yang lebih ramah pengembang dengan memberikan implementasi RPC: Nilai-nilai dari satu utas dapat digunakan dalam utas lain (dan sebaliknya) seperti nilai-nilai lokal.
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 Saat menggunakan WorkerCom dengan SharedWorker Anda harus:
port , dari instance SharedWorker , saat menelepon Workercom.wrap .Workercom.expose dalam panggilan balik onconnect dari pekerja bersama.Kiat Pro: Anda dapat mengakses devtools untuk setiap pekerja bersama yang saat ini berjalan di Chrome dengan pergi ke: chrome: // inspect/#pekerja
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) dan Workercom.expose(value, endpoint?) Tujuan WorkerCom adalah membuat nilai yang terbuka dari satu utas yang tersedia di yang lain. expose Exposes value pada endpoint , di mana endpoint adalah antarmuka seperti postMessage .
wrap membungkus ujung lain dari saluran pesan dan mengembalikan proxy. Proxy akan memiliki semua properti dan fungsi dari nilai yang terpapar, tetapi akses dan doa secara inheren tidak sinkron. Ini berarti bahwa fungsi yang mengembalikan angka sekarang akan mengembalikan janji untuk angka. Sebagai aturan praktis: Jika Anda menggunakan proxy, await di depannya. Pengecualian akan ditangkap dan dilemparkan kembali di sisi lain.
Workercom.installTransfer(name, transferables) & Comlink.proxySecara default, setiap parameter fungsi, nilai pengembalian dan nilai properti objek disalin, dalam arti kloning terstruktur. Kloning terstruktur dapat dianggap sebagai penyalinan yang dalam, tetapi memiliki beberapa keterbatasan. Lihat tabel ini untuk detailnya.
Jika Anda ingin nilai ditransfer daripada disalin - asalkan nilainya atau berisi Transferable - Anda dapat membungkus nilainya dalam panggilan installTransfer() dan memberikan daftar nilai yang dapat ditransfer:
import { installTransfer } from "workercom" ;
installTransfer < ArrayBuffer , string > ( "arraybuffer" , {
canHandle : ( value ) => value instanceof ArrayBuffer ,
serialize : ( value ) => [ _arrayBufferToBase64 ( value ) , [ ] ] ,
deserialize : ( { raw } ) => _base64ToArrayBuffer ( raw ) ,
} ) ; Dihapus Comlink.proxy() . Ini akan terjadi secara otomatis
// myProxy.onready = Comlink.proxy((data) => {
// /* ... */
// });
// * And now
myProxy . onready = ( data ) => {
/* ... */
}Lihat lebih banyak transfer default
Adalah umum bahwa Anda ingin menggunakan WorkerCom untuk menambahkan pendengar acara, di mana sumber acara ada di utas lain:
button . addEventListener ( "click" , myProxy . onClick . bind ( myProxy ) ) ; Meskipun ini tidak akan segera dilemparkan, onClick tidak akan pernah benar -benar dipanggil. Ini karena Event tidak terstruktur yang dapat dikloning atau dapat ditransfer. Sebagai solusi, WorkerCom menawarkan penangan transfer.
Setiap parameter fungsi dan nilai pengembalian diberikan kepada semua penangan transfer terdaftar. Jika salah satu penangan acara yang dapat memproses nilai dengan mengembalikan true dari canHandle() , sekarang bertanggung jawab untuk membuat serialisasi nilai ke data kloning terstruktur dan untuk menghapus nilai nilai. Penangan transfer telah diatur di kedua sisi saluran pesan. Inilah contoh penangan transfer untuk acara:
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 ,
} ) ; Perhatikan bahwa penangan transfer khusus ini tidak akan membuat Event aktual, tetapi hanya objek yang memiliki properti event.target.id dan event.target.classList . Seringkali, ini sudah cukup. Jika tidak, penangan transfer dapat dengan mudah ditambah untuk menyediakan semua data yang diperlukan.
Dukungan Konversi Default untuk function , class , Keluarga Error , Keluarga TypedArray
Workercom.releaseProxy Setiap proxy yang dibuat oleh WorkerCom memiliki metode [releaseProxy] . Menyebutnya akan melepaskan proxy dan objek yang terbuka dari saluran pesan, yang memungkinkan kedua ujungnya dikumpulkan.
const proxy = wrap ( port ) ;
// ... use the proxy ...
proxy [ releaseProxy ] ( ) ;Workercom.createEndpoint Setiap proxy yang dibuat oleh WorkerCom memiliki metode [createEndpoint] . Menyebutnya akan mengembalikan MessagePort baru, yang telah dihubungkan ke objek yang sama dengan proxy yang telah dipanggil [createEndpoint] .
const port = myProxy [ createEndpoint ] ( ) ;
const newProxy = wrap ( port ) ;Workercom.windowEndpoint(window, context = self, targetOrigin = "*") Pekerja Windows dan Web memiliki varian postMessage yang sedikit berbeda. Jika Anda ingin menggunakan WorkerCom untuk berkomunikasi dengan iframe atau jendela lain, Anda perlu membungkusnya dengan windowEndpoint() .
window adalah jendela yang harus dikomunikasikan dengan. context adalah EventTarget di mana pesan dari window dapat diterima (sering self ). targetOrigin diteruskan ke postMessage dan memungkinkan untuk memfilter pesan berdasarkan asal. Untuk detailnya, lihat dokumentasi untuk Window.postMessage .
Sebagai contoh penggunaan, lihat contoh non-pekerja di folder docs .
WorkerCom memang menyediakan tipe naskah. Saat Anda expose() sesuatu dari tipe T , panggilan wrap() yang sesuai akan mengembalikan sesuatu dari tipe Workercom.Remote<T> . Sementara jenis ini telah diuji pertempuran selama beberapa waktu sekarang, itu diimplementasikan berdasarkan upaya terbaik. Ada beberapa nuansa yang sangat sulit jika bukan tidak mungkin untuk menyandikan dengan benar dalam sistem tipe TypeScript. Kadang -kadang mungkin diperlukan untuk memaksa jenis tertentu menggunakan as unknown as <type> .
WorkerCom bekerja dengan modul worker_threads Node.
Lisensi MIT