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
Worker
should 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
Worker
could 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.