Post 网络工作者的功能
Post function to webworker
如何将函数(的副本)从我的主线程发送到我的工作线程?
每当我尝试:worker.postMessage({data, func: (data) => data)
,firefox 都会给我一条错误消息:DataCloneError:无法克隆对象。
至于Chrome,消息不同,但错误仍然存在:Uncaught DOMException: Failed to execute 'postMessage' on 'Worker': Object could not被克隆。
尚未对此进行测试,但似乎从规范来看,只有可以发送给 Worker 的对象才是 "Transferable" 对象:
https://developer.mozilla.org/en-US/docs/Web/API/Transferable
我找到了一些例子,第一个过程没有详细说明,但我猜他使用了一种或URL编码,对于一个对象,它可以转换为JSON 就像第二个例子。
How to pass functions to JavaScript Web Worker
Passing objects to a web worker
几天后我也必须这样做,我可以随时更新我将要测试的内容..
是的,这是可能的,我做到了,而且更好的是我可以创建没有 js 文件的网络工作者,只需要使用由 javascript 代码生成的 Blob 文件.
setInterval(()=>{console.log("non bloked " + Math.random())}, 900)
console.log("starting blocking code in Worker")
console.time("blocked")
genericWorker(window, ["blockCpu", function (block){
block(10000) //This blockCpu function is defined below
return `\n\nbla ${123123*2312} 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();
var result = 0
while(true) {
result += Math.random() * Math.random();
if (new Date().getTime() > now +ms)
return;
}
}
如何将函数(的副本)从我的主线程发送到我的工作线程?
每当我尝试:worker.postMessage({data, func: (data) => data)
,firefox 都会给我一条错误消息:DataCloneError:无法克隆对象。
至于Chrome,消息不同,但错误仍然存在:Uncaught DOMException: Failed to execute 'postMessage' on 'Worker': Object could not被克隆。
尚未对此进行测试,但似乎从规范来看,只有可以发送给 Worker 的对象才是 "Transferable" 对象: https://developer.mozilla.org/en-US/docs/Web/API/Transferable
我找到了一些例子,第一个过程没有详细说明,但我猜他使用了一种或URL编码,对于一个对象,它可以转换为JSON 就像第二个例子。
How to pass functions to JavaScript Web Worker
Passing objects to a web worker
几天后我也必须这样做,我可以随时更新我将要测试的内容..
是的,这是可能的,我做到了,而且更好的是我可以创建没有 js 文件的网络工作者,只需要使用由 javascript 代码生成的 Blob 文件.
setInterval(()=>{console.log("non bloked " + Math.random())}, 900)
console.log("starting blocking code in Worker")
console.time("blocked")
genericWorker(window, ["blockCpu", function (block){
block(10000) //This blockCpu function is defined below
return `\n\nbla ${123123*2312} 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();
var result = 0
while(true) {
result += Math.random() * Math.random();
if (new Date().getTime() > now +ms)
return;
}
}