Skip to content

Instantly share code, notes, and snippets.

@zz85
Last active June 17, 2019 20:52
Show Gist options
  • Star 2 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save zz85/25564f1910f1877c39c25ace5e5159bc to your computer and use it in GitHub Desktop.
Save zz85/25564f1910f1877c39c25ace5e5159bc to your computer and use it in GitHub Desktop.
Greenlet.js Annotated
// This is @zz85's attempt to understand and annotate the greenlet.js lib
// from https://github.com/developit/greenlet/blob/master/greenlet.js
/** Move an async function into its own thread.
* @param {Function} fn The (async) function to run in a Worker.
*/
export default function greenlet(fn) { // greenlet takes in a function as argument
let w = new Worker( // creates a web worker
URL.createObjectURL( // that has a local url
new Blob([ // created from a blob that has the following content
'onmessage =' + ( // function to be called when the message event occurs from main thread
f => // fat arrow function to return another function. f is iife passed function arg `fn`
({ data }) // that destructures an object with a field data as it's argument
=> Promise.resolve() // that is a promise
.then(
() => f.apply(f, data[1]) // run it's original function f, with data[1] as arguments
).then(
d => { postMessage([data[0], null, d]); }, // postMessage with d as 3rd arg if promise is successfull
e => { postMessage([data[0], '' + e ]); } // otherwise post error as 2nd argument
)
) + '(' + fn + ')' // this uses a function to string hack to pass the source code as a string. this is a iife
])
)
),
c = 0, // counter
p = {}, // an object tracking promise resolvers and rejectors
w.onmessage = // callback from worker
({ data: [c,e,d] }) => { // destructures message event's data into 3 components
p[c] // promise callback for this message call
[e ? 1 : 0] // if error, takes first array entry, otherwise second
(e||d); // and passes error otherwise original data
delete p[c]; // clean up promise callback
};
return (...a) => // returns a function when invoked with arguments a
new Promise( (y, n) => { // returns a promise
p[++c] = [y, n]; // resolver and rejector are stored in an array with a counter
w.postMessage([c, a]); // posts to worker with calling id, and arguments
});
}
@zz85
Copy link
Author

zz85 commented Jan 29, 2018

@developit in line 13 above, ({ data }) could also be destructured as ({ data: [c, a] }) to make it clearer.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment