This class is used to execute remote methods located on the module loaded into a separate thread via the workers framework.
The workers.open() method loads the script and returns a Promise to the main thread. Once resolved, you gain access to an instance of Connection, which allows you to call methods of the module via invoke() or broadcast() methods.
Invoking a remote methodTo delegate work to a worker, you need to create a module that exposes functions or a class that will be instantiated by the framework. Each remote method can accept one parameter only. The parameter value can be any primitive type, or JavaScript object handled by the structured clone algorithm, or a JavaScript Promise that resolves with one of them.
For example, let's create a simple worker that calculates the sum of an array of numbers.
// Module loaded in worker : calculator.js
export function getSum(numbers) {
let sum = 0;
for (let i = 0; i < numbers.length; i++) {
sum += numbers[i];
}
return sum;
}
Now we load the calculator module into a worker and invoke its getSum
function.
// Module loaded in main thread
export function getSumAsync(numbers) {
let connection = null;
return workers.open("./calculator.js")
.then(function(conn) {
// Keep the connection reference to later close it.
connection = conn;
return connection.invoke("getSum", numbers);
})
.then(function(result) {
// close the connection
connection.close();
connection = null;
return result;
});
}
// Invoke our method.
getSumAsync([0, 2, 4, 6, 8])
.then(function(result) {
console.log("Result:", result);
});
Passing multiple parameters
As mentioned above, the remote methods loaded with worker can only accept one parameter. However, to pass multiple parameters to the remote method, use a JavaScript object with multiple key-value pairs.
The example below shows a function that multiplies an array of numbers by a factor.
// Module loaded in worker : calculator.js
export function mapMultiply(params) {
// params has numbers and factor values.
let numbers = params.numbers;
let factor = params.factor;
for (let i = 0; i < numbers.length; i++) {
numbers[i] *= factor;
}
return numbers;
}
To invoke this function, an object with two properties is passed into the function.
// Module loaded in main thread
export function mapMultiplyAsync(numbers, factor) {
let connection = null;
return workers.open("./calculator.js")
.then(function(conn) {
// Keep the connection reference to later close it.
connection = conn;
// invoke mapMultiply and pass in object with two key-value pairs.
return connection.invoke("mapMultiply", {
numbers: numbers,
factor: factor
});
})
.then(function(result) {
// close the connection after we are done.
connection.close();
connection = null;
return result;
});
}
// Invoke the method.
mapMultiplyAsync([0, 2, 4, 6, 8], 2)
.then(function(result) {
console.log("Result:", result);
});
Using transferables
Transferable
objects can be used to transfer data between main and worker thread to avoid copying the data. With this approach, the ownership of the object is transferred to the other context. Use this technique to transfer large chuck of memory with ArrayBuffers, a MessagePort, or an ImageBitmap.
Note
The Transferable
interface technically no longer exists. The functionality of Transferable
objects still exists, however, but is implemented at a more fundamental level (technically speaking, using the [Transferable]
WebIDL extended attribute). See also Transferable objects.
To transfer an object to the worker, use the transferList
parameter of the invoke()
method. For the remote method to return or resolve with a transferable object, the result returned must have two properties: result
and transferList
, result
being an object and transferList
the array of transferable objects. Note that every transferable object in transferList
should be in the object structure of result
.
Let's revisit the previous example to explore transferable objects.
// Module loaded in worker : calculator.js
export function mapMultiplyFloat64(params) {
// the numbers parameter is an ArrayBuffer
// we create a typed array from it.
let numbers = new Float64Array(params.numbers);
let factor = params.factor;
for (let i = 0; i < numbers.length; i++) {
numbers[i] *= factor;
}
// Transfer back the buffer
return {
result: numbers.buffer,
transferList: [numbers.buffer]
};
}
On the main thread, we transfer the input typed array's buffer. Then we recreate a Float64Array back from the returned buffer.
// Module loaded in main thread
export function mapMultiplyFloat64Async(numbers, factor) {
let connection = null;
return workers.open("./calculator.js")
.then(function(conn) {
// Keep the connection reference to later close it.
connection = conn;
return connection.invoke("mapMultiplyFloat64", {
numbers: numbers,
factor: factor
});
})
.then(function(result) {
// close the connection after we are done.
connection.close();
connection = null;
return result;
});
}
// Invoke our method.
let floats = new Float64Array(5);
floats[0] = 0;
floats[1] = 2;
floats[2] = 4;
floats[3] = 6;
floats[4] = 8;
mapMultiplyFloat64Async(floats, 2)
.then(function(result) {
let resultFloats = new Float64Array(result);
console.log("Result:", resultFloats);
});
RetroSearch is an open source project built by @garambo | Open a GitHub Issue
Search and Browse the WWW like it's 1997 | Search results from DuckDuckGo
HTML:
3.2
| Encoding:
UTF-8
| Version:
0.7.4