Skip to content

Commit 5b8fdbe

Browse files
committed
Reduce size to 278b, add additional annotation comments
1 parent d523352 commit 5b8fdbe

File tree

2 files changed

+38
-27
lines changed

2 files changed

+38
-27
lines changed

greenlet.js

Lines changed: 36 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -1,29 +1,28 @@
11
/** Move an async function into its own thread.
22
* @param {Function} asyncFunction An (async) function to run in a Worker.
3+
* @public
34
*/
45
export default function greenlet(asyncFunction) {
5-
// Create an "inline" worker
6+
// Create an "inline" worker (1:1 at definition time)
67
let worker = new Worker(
78
// The URL is a pointer to a stringified function (as a blob object)
89
URL.createObjectURL(
910
new Blob([
1011
// Register our wrapper function as the message handler
11-
'onmessage=('+(
12-
// f() is the user-supplied async function
13-
userFunc => ({ data }) => Promise.resolve().then(
14-
// invoking within then() captures exceptions in f() as rejections
15-
() => userFunc.apply(userFunc, data[1])
16-
).then(
17-
d => {
18-
// success handler - callback(id, null, result)
19-
postMessage([data[0], null, d]);
20-
},
21-
e => {
22-
// error handler - callback(id, err)
23-
postMessage([data[0], ''+e]);
24-
}
25-
)
26-
)+')('+asyncFunction+')' // pass user-supplied function to the closure
12+
'onmessage=(' + (
13+
// userFunc() is the user-supplied async function
14+
userFunc => e => {
15+
// Invoking within then() captures exceptions in userFunc() as rejections
16+
Promise.resolve(e.data[1]).then(
17+
userFunc.apply.bind(userFunc, userFunc)
18+
).then(
19+
// success handler - callback(id, SUCCESS(0), result)
20+
d => { postMessage([e.data[0], 0, d]); },
21+
// error handler - callback(id, ERROR(1), error)
22+
e => { postMessage([e.data[0], 1, ''+e]); }
23+
);
24+
}
25+
) + ')(' + asyncFunction + ')' // pass user-supplied function to the closure
2726
])
2827
)
2928
),
@@ -34,18 +33,29 @@ export default function greenlet(asyncFunction) {
3433
// Outward-facing promises store their "controllers" (`[request, reject]`) here:
3534
promises = {};
3635

37-
// Handle RPC results/errors coming back out of the worker
38-
worker.onmessage = ({ data: [id, err, result] }) => {
36+
/** Handle RPC results/errors coming back out of the worker.
37+
* Messages coming from the worker take the form `[id, status, result]`:
38+
* id - counter-based unique ID for the RPC call
39+
* status - 0 for success, 1 for failure
40+
* result - the result or error, depending on `status`
41+
*/
42+
worker.onmessage = e => {
3943
// invoke the promise's resolve() or reject() depending on whether there was an error.
40-
promises[id][err ? 1 : 0](err || result);
44+
promises[e.data[0]][e.data[1]](e.data[2]);
45+
4146
// ... then delete the promise controller
42-
delete promises[id];
47+
promises[e.data[0]] = null;
4348
};
4449

4550
// Return a proxy function that forwards calls to the worker & returns a promise for the result.
46-
return (...args) => new Promise( (resolve, reject) => {
47-
promises[++currentId] = [resolve, reject];
48-
// Send an RPC call to the worker - call(id, params)
49-
worker.postMessage([currentId, args]);
50-
});
51+
return function(args) {
52+
args = [].slice.call(arguments);
53+
return new Promise(function() {
54+
// Add the promise controller to the registry
55+
promises[++currentId] = arguments;
56+
57+
// Send an RPC call to the worker - call(id, params)
58+
worker.postMessage([currentId, args]);
59+
});
60+
};
5161
}

package.json

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,8 @@
1313
"eslintConfig": {
1414
"extends": "eslint-config-developit",
1515
"rules": {
16-
"prefer-spread": 0
16+
"prefer-spread": 0,
17+
"prefer-rest-params": 0
1718
}
1819
},
1920
"files": [

0 commit comments

Comments
 (0)