diff --git a/src/ch08/exercises.ts b/src/ch08/exercises.ts index d22cb87..ee5e16b 100644 --- a/src/ch08/exercises.ts +++ b/src/ch08/exercises.ts @@ -57,7 +57,7 @@ function createProtocol

(script: string) { new Promise((resolve, reject) => { let worker = new Worker(script) worker.onerror = reject - worker.onmessage = event => resolve(event.data.data) + worker.onmessage = event => resolve(event.data) worker.postMessage({command, args}) }) } @@ -73,32 +73,59 @@ parallelDeterminant([[1, 2], [3, 4]]).then( // WorkerScript.ts -let handlers: { - [C in keyof MatrixProtocol]: ( - ...args: MatrixProtocol[C]['in'] - ) => MatrixProtocol[C]['out'] -} = { - determinant(matrix) { - return determinant(matrix) - }, - ['dot-product'](a, b) { - return dotProduct(a, b) - }, - invert(matrix) { - return invert(matrix) +type Data< + P extends Protocol, + C extends keyof P = keyof P +> = C extends C + ? {command: C; args: P[C]['in']} + : never + +function handle( + data: Data +): MatrixProtocol[typeof data.command]['out'] { + switch (data.command) { + case 'determinant': + return determinant(...data.args) + case 'dot-product': + return dotProduct(...data.args) + case 'invert': + return invert(...data.args) } } -onmessage = ({ - data: {command, args} -}: { - data: {command: C; args: MatrixProtocol[C]['in']} -}) => { - let handler = handlers[command] - let result = handler(...args) - postMessage(result) -} +onmessage = ({data}) => postMessage(handle(data)) declare function determinant(matrix: Matrix): number declare function dotProduct(matrixA: Matrix, matrixB: Matrix): Matrix declare function invert(matrix: Matrix): Matrix + +// 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`. + +// MainThread.ts +import {fork} from 'child_process' + +function createProtocolCP

(script: string) { + return (command: K) => (...args: P[K]['in']) => + new Promise((resolve, reject) => { + let child = fork(script) + child.on('error', reject) + child.on('message', resolve) + child.send({command, args}) + }) +} + +let runWithMatrixProtocolCP = createProtocolCP( + './ChildThread.js' +) +let parallelDeterminantCP = runWithMatrixProtocolCP('determinant') + +parallelDeterminantCP([[1, 2], [3, 4]]).then( + determinant => console.log(determinant) // -2 +) + +// ChildThread.ts + +// type Data ... +// function handle ... + +process.on('message', data => process.send!(handle(data)))