我正在做一个客户端模拟,它可以实时进行后台计算和视图刷新。但是,由于模拟始终是实时的,CPU 最终会在用户输入和编辑过程中进行大量不必要的工作。
我想要实现的是一种杀死用户事件的整个序列的方法。
主应用程序中的预期用法:
var sequence = new Sequence(heavyFunc1, heavyFunc2, updateDom);
document.addEventListener("click", sequence.stop)
sequence.run() //all the heavy computation runs until told to stop
网络工作者的预期用法:
var sequence = new Sequence(heavyFunc1, heavyFunc2, self.postmessage);
self.onmessage = function(e) {
if (e.data === 'stop') msg = sequence.stop;
else msg = sequence.run(e.data); //resets and restarts
};
我环顾四周,可以想到以下工具和模式:
setTimout(fcn,0) || setImmediate(fcn) shim :将主脚本和工作线程中的序列内的各个步骤包装起来,setTimeout(fcn,0)
以在序列结束之前处理新事件。
killFlag = false;
window.addEventListener('keypress', function() {killFlag = true});
//this exampe works only with setTimeout, fails with setImmediate lib
var interruptibleSequence = function(tasks) {
var iterate = function() {
if (killFlag || !tasks.length) return;
tasks.shift()();
if (tasks.length) window.setTimeout(iterate,0);
};
iterate();
};
此示例与 setTimeout 一起使用,但在按键事件总是最后出现的 setImmediate 中失败。
debounce :这是典型的答案,似乎不适用于我的情况。延迟和批处理用户输入会以更长的处理时间为代价部分降低处理强度。
Promises:我已经在对工作结果使用 Promise,并且可以在步骤之间引入额外的 Promise 来中断序列并处理新事件。我已经尝试(但失败了)使用标志检查或Promise.race
.
带杀旗
killFlag = false;
window.addEventListener('keypress', function() {killFlag = true});
//does not work. promises get priority and event is only triggered last
var interruptibleSequence = function(tasks) {
var seq = Promise.resolve();
tasks.forEach(function(task){
seq = seq.then(function() {
if (killFlag) return;
else task();
});
});
};
与Promise.race
var killTrigger;
var killPromise = new Promise(function(res,rej){killTrigger = rej});
window.addEventListener('keypress', killTrigger());
//does not work. promises get priority and event is only triggered last
var raceToFailure = function(tasks) {
var seq = Promise.resolve();
tasks.forEach(function(task){
seq = Promise.race([seq.then(task),killPromise]);
});
};
问题 在事件中终止序列的推荐模式是什么?