我有一个监听器来监听内容的变化,一旦内容被修改,它就会发出处理函数:
$('#editor').on('onchange', () => changeHandler('...','...'));
function changeHandler(filePath, content){
var ws = fs.createWriteStream(filePath, 'utf8');
ws.write(content);
}
我的问题是'onchange'经常发生,因此'write file'经常处理,在此期间它可能会丢失数据。 有人可以提出任何建议吗?
更新 现在我根据下面的答案更改了代码:
this.buffer = null; //used to cache
// once content changed, maybe too often
changeHandler() {
if (this.editor.curOp && this.editor.curOp.command.name) {
var id = $('.nav-items li.active .lk-hosts').attr('data-hosts-id');
var content = this.editor.getValue();
// cache data, not immediately write to file
this.buffer = {id: id, content: content};
}
}
setInterval(()=> {
// means there's data in cache
if (this.buffer !== null) {
let id = this.buffer.id;
let content = this.buffer.content;
// reset cache to null
this.buffer = null;
// write file
this.writeContent(id, content, (err)=> {
})
}
}, 800);
感谢所有答案!
答案 0 :(得分:1)
下面的示例显示了如何进行去抖动事件处理,尽管它不是node.js代码,它在概念上是相同的。
// eventEmitter variable to use
var emitter = new EventEmitter();
// dom element change event
$('#editor').on('input', function(event) {
emitter.emit('changeEvent', event.target.value);
});
// event listener, which debounces change event of input
emitter.on('changeEvent', debounce(function(data) {
writeFile('li', data);
}, 1000)); // <== debounce for 1second
// sample emitter, for demo
// we don't have access to nodejs EventEmitter class in Stackoverflow
// don't use in production
function EventEmitter() {
var callbacks = [];
return {
on: function(eventName, fn) {
callbacks.push({
eventName: eventName,
callback: fn
})
},
emit: function(eventName, payload) {
var fn = callbacks.find(function(item) {
return item.eventName === eventName;
});
if (fn) {
fn.callback(payload);
}
}
}
}
// simple logger for demo purpose
// emulates write file
function writeFile(name, content) {
var $elem = $(document.createElement(name));
$elem.text(content);
$('#logger').append($elem);
}
// throttle function - reduces fn call with timeout
// credits: https://remysharp.com/2010/07/21/throttling-function-calls
function debounce(fn, delay) {
var timer = null;
return function() {
var context = this,
args = arguments;
clearTimeout(timer);
timer = setTimeout(function() {
fn.apply(context, args);
}, delay);
};
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<textarea id="editor" placeholder="Enter text, this will emit change event"></textarea>
<p>
Notice the 1sec throttle (write something, pause for 1sec, write again)
</p>
<ul id="logger"></ul>
去抖功能也可用于textarea更改事件
// debounce emitting
$('#editor').on('input', debounce(function(event) {
emitter.emit('changeEvent', event.target.value);
}, 1000));
// write file when received event without debounce
emitter.on('changeEvent', function(data){
logElement('li', data);
});
答案 1 :(得分:0)
Underscore库具有_.throttle()
和_.debounce()
功能。
答案 2 :(得分:0)
为什么不简单地构建一个缓冲区来收集书面文本,然后只有当你有一定数量的写入时才写入文件:
$('#editor').on('onchange', () => changeHandler('...','...'));
var writeBuffer = ''; // can also make this an array
var writeBufferSize = 0;
var filePath = 'path_to_file';
var ws = fs.createWriteStream(filePath, 'utf8');
function changeHandler(content){
if (writeBufferSize == SOME_THRESHOLD) {
ws.write(writeBuffer);
writeBuffer = '';
writeBufferSize = 0;
} else {
writeBuffer += content + '\n';
writeBufferSize++;
}
}
如果选择的写入缓冲区阈值太大,您可能希望将写入委托给某个工作线程并行完成,在这种情况下,您可以创建另一个临时写入缓冲区来填充正在写原文,然后切换两个。