Skip to content

Instantly share code, notes, and snippets.

@ayatty
Created March 14, 2019 15:21
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save ayatty/06fd745c115723a8e0f8f2e639477fe9 to your computer and use it in GitHub Desktop.
Save ayatty/06fd745c115723a8e0f8f2e639477fe9 to your computer and use it in GitHub Desktop.
Thread like context for Node.js (using async_hooks)
const asyncHooks = require('async_hooks');
const asyncMap = {}
asyncHooks.createHook({
init(asyncId, type, triggerAsyncId) {
const parent = asyncHooks.executionAsyncId();
// 親がスレッドに属していれば子も属す
if (asyncMap[parent]) {
asyncMap[asyncId] = asyncMap[parent];
// そうでなければメインスレッドに所属
} else {
asyncMap[asyncId] = mainThread;
}
},
destroy(asyncId) {
delete(asyncMap[asyncId]);
},
promiseResolve(asyncId) {
delete(asyncMap[asyncId]);
},
}).enable();
class Thread {
constructor(entryFunction, threadLabel) {
this.entryFunction = entryFunction;
this.label = threadLabel;
}
run() {
const self = this;
const args = arguments;
return new Promise((resolve, reject) => {
setImmediate(() => {
asyncMap[asyncHooks.executionAsyncId()] = self;
try {
resolve(self.entryFunction(...args));
} catch (e) {
reject(e);
}
});
});
}
}
const mainThread = new Thread(null, 'MainThread');
function getCurrentThread() {
const eid = asyncHooks.executionAsyncId();
if (asyncMap[eid]) {
return asyncMap[eid];
}
return mainThread;
}
//
// ここからは動作確認用のコード
//
function printAsyncId(label) {
const cThread = getCurrentThread();
process._rawDebug(`(${cThread.label})${label}: eid=${asyncHooks.executionAsyncId()} tid=${asyncHooks.triggerAsyncId()}`);
}
function delayPrint(delay) {
printAsyncId('delayPrint start');
return new Promise((resolve, reject) => {
setTimeout(() => {
printAsyncId('delayPrint on timeout');
console.log(getCurrentThread().text);
printAsyncId('delayPrint before resolve');
resolve();
//reject();
}, delay);
});
}
async function asyncFunction(text, delay) {
printAsyncId('run start');
getCurrentThread().text = text;
await delayPrint(delay);
printAsyncId('run end');
}
printAsyncId('Main-Start');
const threadA = (new Thread(asyncFunction, 'aaa-delayPrint')).run('aaaaa', 1500);
printAsyncId('Main-Middle1');
const threadB = (new Thread(asyncFunction, 'bbb-delayPrint')).run('bbbbb', 1000);
const threadC = (new Thread(console.log, 'console.log')).run('ccccc');
printAsyncId('Main-End');
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment