Finally async
/await
will be supported in all major browser soon except IE.
So now we can start writing more readable code with async
/<
First, are your code a blocking-code?
If yes, remember that javascript is single thread, so you cannot run two synchronous codes, for example two loops (for or while) at the same time.
But, it is possible to achieve that using Web Workers, I managed to execute functions in generic web workers and without using separated js files.
setInterval(()=>{console.log("non blocked " + Math.random())}, 900)
console.log("start blocking code in parallel in web Worker")
console.time("blocked")
genericWorker(window, ["blockCpu", function (block){
block(10000) //This blockCpu function is defined below
return "\n\nbla bla\n" //This is catched in the resolved promise
}]).then(function (result){
console.timeEnd("blocked")
console.log("End of blocking code", result)
})
.catch(function(error) { console.log(error) })
/* A Web Worker that does not use a File, it create that from a Blob
@cb_context, The context where the callback functions arguments are, ex: window
@cb, ["fn_name1", "fn_name2", function (fn1, fn2) {}]
The callback will be executed, and you can pass other functions to that cb
*/
function genericWorker(cb_context, cb) {
return new Promise(function (resolve, reject) {
if (!cb || !Array.isArray(cb))
return reject("Invalid data")
var callback = cb.pop()
var functions = cb
if (typeof callback != "function" || functions.some((fn)=>{return typeof cb_context[fn] != "function"}))
return reject(`The callback or some of the parameters: (${functions.toString()}) are not functions`)
if (functions.length>0 && !cb_context)
return reject("context is undefined")
callback = fn_string(callback) //Callback to be executed
functions = functions.map((fn_name)=> { return fn_string( cb_context[fn_name] ) })
var worker_file = window.URL.createObjectURL( new Blob(["self.addEventListener('message', function(e) { var bb = {}; var args = []; for (fn of e.data.functions) { bb[fn.name] = new Function(fn.args, fn.body); args.push(fn.name)}; var callback = new Function( e.data.callback.args, e.data.callback.body); args = args.map(function(fn_name) { return bb[fn_name] }); var result = callback.apply(null, args) ;self.postMessage( result );}, false)"]) )
var worker = new Worker(worker_file)
worker.postMessage({ callback: callback, functions: functions })
worker.addEventListener('error', function(error){ return reject(error.message) })
worker.addEventListener('message', function(e) {
resolve(e.data), worker.terminate()
}, false)
//From function to string, with its name, arguments and its body
function fn_string (fn) {
var name = fn.name, fn = fn.toString()
return { name: name,
args: fn.substring(fn.indexOf("(") + 1, fn.indexOf(")")),
body: fn.substring(fn.indexOf("{") + 1, fn.lastIndexOf("}"))
}
}
})
}
//random blocking function
function blockCpu(ms) {
var now = new Date().getTime(), result = 0
while(true) {
result += Math.random() * Math.random();
if (new Date().getTime() > now +ms)
return;
}
}