can-connect/data/worker/worker
Connects a connection to another connection in a worker thread.
dataWorker( baseConnection )
If a Worker
is provided, overwrites the "data interface methods" to package the arguments and send them as
part of a postMessage to the Worker.
If a Worker is not provided, it is assumed "data-worker" is being added
within a worker thread. It listens to messages sent to the Worker, calls the specified "data interface method"
and sends a message back with the result.
Any data methods called on the window connection will wait until the worker connection
has established a handshake.
Use
The best way to use data/worker is to create a connection module that works when loaded in
either the window or in a Worker.
This pattern tends to work even if workers are not supported.
The following creates a connection that does the work of cache-requests, data/url, and memory-cache in a worker thread.
The todo_connection module can be found here
and looks like the following:
import connect from "can-connect";
import fixture from "can-fixture";
// If we are in the main thread, see if we can load this same
// connection in a worker thread.
let worker;
if ( typeof document !== "undefined" ) {
worker = new Worker( System.stealURL + "?main=can-connect/data/worker/demo/todo_connection" );
}
// create cache connection
const cache = connect( [
require( "can-connect/data/memory-cache/" )
], {
name: "todos"
} );
// Create the main connection with everything you need. If there is a worker,
// all data interface methods will be sent to the worker.
const todosConnection = connect( [
require( "can-connect/data/url/url" ),
require( "can-connect/cache-requests/cache-requests" ),
require( "can-connect/data/worker/worker" ),
require( "can-connect/constructor/constructor" ),
require( "can-connect/constructor/store/store" )
], {
url: "/todos",
cacheConnection: cache,
worker: worker,
name: "todos"
} );
fixture.delay = 1000;
fixture( {
"GET /todos": function( request ) {
return { data: [
{ id: 1, name: "wash dishes" },
{ id: 2, name: "mow lawn" },
{ id: 3, name: "do laundry" }
] };
}
} );
export default todosConnection;
The things to notice:
A
Workershould be passed as the worker option that loads a connection with the same name as the connection in thewindow. In thise case, the same connection module is loaded so everything works.A single
Workercould load multiple connection modules and perform other behaviors.
Split Connection Logic
THe previous example used a single module that was loaded by both the window and the worker.
This doesn't have to be the case. Two different modules could be used. For example, todo-window.js and
todo-worker.js. Each might look like:
// todo-window.js
const workerURL = System.stealURL + "?main=app/models/todo-worker";
const todoConnection = connect( [
require( "can-connect/data/worker/worker" ),
require( "can-connect/constructor/constructor" ),
require( "can-connect/constructor/store/store" )
], {
worker: new Worker( workerURL ),
name: "todos"
} );
// todo-worker.js
const cache = connect( [
require( "can-connect/data/memory-cache/memory-cache" )
], {
name: "todos-cache"
} );
const todoConnection = connect( [
require( "can-connect/data/url/url" ),
require( "can-connect/cache-requests/cache-requests" ),
require( "can-connect/data/worker/worker" )
], {
url: "/todos",
cacheConnection: cache,
name: "todos"
} );
However, the problem with the two-module approach is that it will not work if Workers are not supported by your browser.