Last active
November 8, 2018 19:58
-
-
Save wentout/263f7e73ba4f14c1a125b40a1aafa8a0 to your computer and use it in GitHub Desktop.
CLS implementation using wrapped function. Polling problem shown from line 111.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
'use strict'; | |
// HOOKS EXAMPLE START | |
var counter = 0; | |
var currentId = 0; | |
var hooks = { | |
init: [], | |
before: [], | |
after: [], | |
// unable to implement real destroy | |
// cause no access to GC | |
destroy: [] | |
}; | |
// we wouldn't implement hookClearTimeout, | |
// cause it long for just an example | |
// in real life same code wraps setTimeout in node!!! | |
var hookSetTimeoout = function (cb, t, ...params) { | |
counter++; | |
hooks.init.forEach(function (hook) { | |
hook(counter, currentId, cb); | |
}); | |
var runWrapper = function (hook) { | |
var destroyId = currentId; | |
hooks.destroy.forEach(function (hook) { | |
// need to skip one else frame | |
// before deleting | |
setTimeout(function () { | |
hook(this); // previous currentId | |
}.bind(destroyId), 0); | |
}); | |
currentId = this; | |
hooks.before.forEach(function (hook) { | |
hook(currentId); | |
}); | |
cb.call(null, ...params); | |
hooks.after.forEach(function (hook) { | |
hook(currentId); | |
}); | |
}.bind(counter); | |
setTimeout(runWrapper, t); | |
}; | |
// HOOKS EXAMPLE STOP | |
// [C|T]LS EXAMPLE START | |
var contexts = {}; | |
var currentContext; | |
hooks.init.push(function (asyncId, triggerId) { | |
if (currentContext) { | |
// context start from wrapped function | |
contexts[asyncId] = currentContext; | |
return; | |
} | |
contexts[asyncId] = contexts[triggerId]; | |
}); | |
hooks.before.push(function (asyncId) { | |
currentContext = contexts[asyncId]; | |
}); | |
hooks.after.push(function () { | |
currentContext = undefined; | |
}); | |
hooks.destroy.push(function (asyncId) { | |
// delete contexts[asyncId]; | |
}); | |
// won't implement stop tracing! | |
var cls = { | |
getData() { | |
return currentContext; | |
}, | |
setData(data, cb) { | |
currentContext = data; | |
cb(); | |
currentContext = undefined;; | |
} | |
}; | |
// [C|T] EXAMPLE STOP | |
// WORKING EXAMPLE CODE START | |
cls.setData('test', function () { | |
console.log('0', cls.getData()); | |
hookSetTimeoout(function () { | |
console.log('1', cls.getData()); | |
}, 100); | |
}); | |
// WORKING EXAMPLE CODE STOP | |
var pollingTasks = []; | |
var pollingRunner = function () { | |
pollingTasks.forEach(function (task) { | |
task(); | |
}); | |
pollingTasks = []; | |
hookSetTimeoout(pollingRunner, 100); | |
}; | |
hookSetTimeoout(pollingRunner, 100); | |
pollingTasks.push(function () { | |
console.log('! must be undefined : ', cls.getData()); | |
}); | |
cls.setData('failure test', function () { | |
console.log('! exists, good : ', cls.getData()); | |
pollingTasks.push(function () { | |
console.log('! will be undefined, WRONG : ', cls.getData()); | |
}); | |
}); |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
'use strict'; | |
// HOOKS EXAMPLE START | |
var counter = 0; | |
var currentId = 0; | |
var hooks = { | |
init: [], | |
before: [], | |
after: [], | |
// unable to implement real destroy | |
// cause no access to GC | |
destroy: [] | |
}; | |
// we wouldn't implement hookClearTimeout, | |
// cause it long for just an example | |
// in real life same code wraps setTimeout in node!!! | |
var hookSetTimeoout = function (cb, t, ...params) { | |
counter++; | |
hooks.init.forEach(function (hook) { | |
hook(counter, currentId, cb); | |
}); | |
var runWrapper = function (hook) { | |
var destroyId = currentId; | |
hooks.destroy.forEach(function (hook) { | |
// need to skip one else frame | |
// before deleting | |
setTimeout(function () { | |
hook(this); // previous currentId | |
}.bind(destroyId), 0); | |
}); | |
currentId = this; | |
hooks.before.forEach(function (hook) { | |
hook(currentId); | |
}); | |
cb.call(null, ...params); | |
hooks.after.forEach(function (hook) { | |
hook(currentId); | |
}); | |
}.bind(counter); | |
setTimeout(runWrapper, t); | |
}; | |
// HOOKS EXAMPLE STOP | |
// [C|T]LS EXAMPLE START | |
// var context = {}; | |
var context = new Map(); | |
context.set(0, 'unreachable'); | |
var stack = [0]; | |
hooks.init.push(function (asyncId, triggerId) { | |
// context[asyncId] = context[triggerId]; | |
context.set(asyncId, context.get(triggerId)); | |
}); | |
hooks.before.push(function (asyncId) { | |
stack.push(asyncId); | |
}); | |
hooks.after.push(function () { | |
stack.pop(); | |
}); | |
hooks.destroy.push(function (asyncId) { | |
context.delete(asyncId); | |
// delete context[asyncId]; | |
}); | |
// won't implement stop tracing! | |
var cls = { | |
getData() { | |
// return context[stack.slice(-1)[0]]; | |
return context.get(stack.slice(-1)[0]); | |
}, | |
setData(data) { | |
// context[stack.slice(-1)[0]] = data; | |
context.set(stack.slice(-1)[0], data); | |
} | |
}; | |
// [C|T] EXAMPLE STOP | |
// WORKING EXAMPLE CODE START | |
hookSetTimeoout(function () { | |
cls.setData('test'); | |
hookSetTimeoout(function () { | |
console.log(cls.getData()); | |
}, 100); | |
}, 100); | |
// WORKING EXAMPLE CODE STOP | |
var pollingTasks = []; | |
var pollingRunner = function () { | |
pollingTasks.forEach(function (task) { | |
task(); | |
}); | |
pollingTasks = []; | |
hookSetTimeoout(pollingRunner, 100); | |
}; | |
hookSetTimeoout(pollingRunner, 100); | |
pollingTasks.push(function () { | |
console.log('must be unreachable > ', cls.getData()); | |
}); | |
// POLLING PROBLEM ITSELF | |
hookSetTimeoout(function () { | |
cls.setData('failure test'); | |
console.log('POLLING PROBLEM ITSELF\n'); | |
pollingTasks.push(function () { | |
console.log('wish to be present, but > ', cls.getData()); | |
}); | |
}, 1000); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
simple demonstration of Async Hooks "under the hood".
Based on Idea itself, but not on real implementation!
Just to Show how it works
and where CLS failed 2 Polling Problem