-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathWorkerAsModule.js
More file actions
90 lines (82 loc) · 2.85 KB
/
WorkerAsModule.js
File metadata and controls
90 lines (82 loc) · 2.85 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
class WorkerAsModule{
constructor(workerPath,handlerByType){
var
worker,
//keep object like {resolve, reject, error} for running promise
promiseStack = [];
if(typeof workerPath==='string'){
worker = new Worker(workerPath,{type:"module"});
}else if(workerPath instanceof Worker){
worker = workerPath;
}else{
worker = self;
}
worker.onmessage = async (event)=>{
let
type = event.data[0],
id = event.data[1],
subtype = event.data[2],
params = event.data[3];
if(type==="request"){
//we receive a request
try{
//get the handler and use it
let
method = handlerByType[subtype];
if(method===undefined){
throw new Error('no method of name '+subtype)
}
//then post the result
worker.postMessage(["response",id,subtype,await method.apply(handlerByType,params)]);
}catch(error){
//or post the error
worker.postMessage(["responseerror",id,subtype,error]);
}
}else if(type==="response"){
//we get a response, so get initial promise and resolve it
let
promise = promiseStack[id];
promiseStack[id] = null;
promise.resolve(params);
}else if(type==="responseerror"){
//we get a response, so get initial promise and reject it with cumulation of stacktace from the other side
let
promise = promiseStack[id],
returnedError = params;
promiseStack[id] = null;
returnedError.stack+='\r\n'+promise.error.stack;
promise.reject(returnedError);
}
}
//FIXME maybe we enter here if a call without await was done and causes error, TODO test and fix
worker.onerror = (event)=>{
console.log('worker.onerror',event)
promiseStack.forEach(o=>o.reject(event));
}
return new Proxy(this,{
get(target, name) {
var
context = {},
method = async function(){
var
id = promiseStack.length,
params = ["request",id,name,Array.prototype.slice.apply(arguments,[0])],//we slice arguments to have a simple Array
error = new Error();
return new Promise((resolve, reject)=>{
promiseStack.push({resolve, reject, error})
worker.postMessage(params,context.transferable?context.transferable:[]);
});
},
result = function(){
return method.apply(context,arguments)
};
result.transfer=function(){
context.transferable = arguments;
return result;
}
return result
}
})
}
}
export default WorkerAsModule;