-
Notifications
You must be signed in to change notification settings - Fork 1
/
client.js
82 lines (73 loc) · 2.35 KB
/
client.js
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
module.exports = function(worker, param) {
var nextId = (function(id) {
return function() {
return ++id
}
})(0)
var operations = {}
worker.onmessage = function(e) {
operations[e.data.id].messageHandler(e.data)
}
var initId = nextId()
return attachSubscribeFunction(initId,
execute(initId, { type: 'init', param: param })
.then(function(result) {
switch(result && result.type) {
case 'process':
return result.result
case 'api':
return Object.assign(result.operations.reduce(function(api, operation) {
api[operation] = function(param) {
return execute(nextId(), { type: 'invoke', param: param, operation: operation })
}
return api
}, {}), {
terminate: function() {
worker.terminate()
}
})
default:
throw new Error('Unrecognized response from worker')
}
})
)
function execute(id, payload) {
return attachSubscribeFunction(id, new Promise(function(resolve, reject) {
operations[id] = {
listeners: [],
messageHandler: function(response) {
// if the message has user content, we want to broadcast this to any registered listeners
if(response.user) {
operations[id].listeners.forEach(function(listener) { listener(response.user) })
} else {
// otherwise, assume the operation completed and resolve or reject the promise accordingly
delete operations[id]
if(response.error)
reject(response.error)
else
resolve(response.result)
}
}
}
worker.postMessage(Object.assign({ id: id }, payload), extractArrayBuffers(payload.param))
}))
}
function attachSubscribeFunction(id, target) {
target.subscribe = function(callback) {
operations[id].listeners.push(callback)
return target
}
return target
}
function extractArrayBuffers(param) {
if(!param)
return
if(param.constructor === ArrayBuffer)
return [param]
return Object.keys(param).reduce(function(buffers, property) {
if(param[property] && param[property].constructor === ArrayBuffer)
buffers.push(param[property])
return buffers
}, [])
}
}