Skip to content

Commit ae39f24

Browse files
committed
fix exercise 2 and add exercise 3
1 parent d8f2d20 commit ae39f24

File tree

1 file changed

+48
-23
lines changed

1 file changed

+48
-23
lines changed

src/ch08/exercises.ts

+48-23
Original file line numberDiff line numberDiff line change
@@ -57,7 +57,7 @@ function createProtocol<P extends Protocol>(script: string) {
5757
new Promise<P[K]['out']>((resolve, reject) => {
5858
let worker = new Worker(script)
5959
worker.onerror = reject
60-
worker.onmessage = event => resolve(event.data.data)
60+
worker.onmessage = event => resolve(event.data)
6161
worker.postMessage({command, args})
6262
})
6363
}
@@ -73,32 +73,57 @@ parallelDeterminant([[1, 2], [3, 4]]).then(
7373

7474
// WorkerScript.ts
7575

76-
let handlers: {
77-
[C in keyof MatrixProtocol]: (
78-
...args: MatrixProtocol[C]['in']
79-
) => MatrixProtocol[C]['out']
80-
} = {
81-
determinant(matrix) {
82-
return determinant(matrix)
83-
},
84-
['dot-product'](a, b) {
85-
return dotProduct(a, b)
86-
},
87-
invert(matrix) {
88-
return invert(matrix)
76+
type Data<
77+
P extends Protocol,
78+
C extends keyof P = keyof P
79+
> = C extends C
80+
? { command: C; args: P[C]['in'] }
81+
: never
82+
83+
function handle(data: Data<MatrixProtocol>): MatrixProtocol[typeof data.command]['out'] {
84+
switch (data.command) {
85+
case 'determinant':
86+
return determinant(...data.args)
87+
case 'dot-product':
88+
return dotProduct(...data.args)
89+
case 'invert':
90+
return invert(...data.args)
8991
}
9092
}
9193

92-
onmessage = <C extends keyof MatrixProtocol>({
93-
data: {command, args}
94-
}: {
95-
data: {command: C; args: MatrixProtocol[C]['in']}
96-
}) => {
97-
let handler = handlers[command]
98-
let result = handler(...args)
99-
postMessage(result)
100-
}
94+
onmessage = ({data}) => postMessage(handle(data))
10195

10296
declare function determinant(matrix: Matrix): number
10397
declare function dotProduct(matrixA: Matrix, matrixB: Matrix): Matrix
10498
declare function invert(matrix: Matrix): Matrix
99+
100+
// 3. Use a mapped type (as in 「8.6.1 In the Browser: With Web Workers★」) to implement a typesafe message-passing protocol for NodeJS's `child_process`.
101+
102+
// MainThread.ts
103+
import {fork} from 'child_process'
104+
105+
function createProtocolCP<P extends Protocol>(script: string) {
106+
return <K extends keyof P>(command: K) => (...args: P[K]['in']) =>
107+
new Promise<P[K]['out']>((resolve, reject) => {
108+
let child = fork(script)
109+
child.on('error', reject)
110+
child.on('message', resolve)
111+
child.send({command, args})
112+
})
113+
}
114+
115+
let runWithMatrixProtocolCP = createProtocolCP<MatrixProtocol>(
116+
'./ChildThread.js'
117+
)
118+
let parallelDeterminantCP = runWithMatrixProtocolCP('determinant')
119+
120+
parallelDeterminantCP([[1, 2], [3, 4]]).then(
121+
determinant => console.log(determinant) // -2
122+
)
123+
124+
// ChildThread.ts
125+
126+
// type Data ...
127+
// function handle ...
128+
129+
process.on('message', data => process.send!(handle(data)))

0 commit comments

Comments
 (0)