Skip to content

Commit 5ea7f09

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

File tree

1 file changed

+50
-23
lines changed

1 file changed

+50
-23
lines changed

src/ch08/exercises.ts

+50-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,59 @@ 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(
84+
data: Data<MatrixProtocol>
85+
): MatrixProtocol[typeof data.command]['out'] {
86+
switch (data.command) {
87+
case 'determinant':
88+
return determinant(...data.args)
89+
case 'dot-product':
90+
return dotProduct(...data.args)
91+
case 'invert':
92+
return invert(...data.args)
8993
}
9094
}
9195

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-
}
96+
onmessage = ({data}) => postMessage(handle(data))
10197

10298
declare function determinant(matrix: Matrix): number
10399
declare function dotProduct(matrixA: Matrix, matrixB: Matrix): Matrix
104100
declare function invert(matrix: Matrix): Matrix
101+
102+
// 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`.
103+
104+
// MainThread.ts
105+
import {fork} from 'child_process'
106+
107+
function createProtocolCP<P extends Protocol>(script: string) {
108+
return <K extends keyof P>(command: K) => (...args: P[K]['in']) =>
109+
new Promise<P[K]['out']>((resolve, reject) => {
110+
let child = fork(script)
111+
child.on('error', reject)
112+
child.on('message', resolve)
113+
child.send({command, args})
114+
})
115+
}
116+
117+
let runWithMatrixProtocolCP = createProtocolCP<MatrixProtocol>(
118+
'./ChildThread.js'
119+
)
120+
let parallelDeterminantCP = runWithMatrixProtocolCP('determinant')
121+
122+
parallelDeterminantCP([[1, 2], [3, 4]]).then(
123+
determinant => console.log(determinant) // -2
124+
)
125+
126+
// ChildThread.ts
127+
128+
// type Data ...
129+
// function handle ...
130+
131+
process.on('message', data => process.send!(handle(data)))

0 commit comments

Comments
 (0)