在 interval 上调用的函数访问全局变量
Function called on interval accesses global variable
我正在异步接收数据(从每秒 0 到 100 点),这些数据将传递给高启动成本函数 extendTraces(data),该函数会更新用户界面。如果我在生成每个点时调用 extendTraces(),用户界面将变得无响应。我发现定期调用该函数并向其传递一个点数组(称为 pointArray)效率更高。
我可以跟踪有多少点被添加到 pointArray 并每添加 20 次调用 extendTraces(pointArray):
//inside asynchronous function
pointArray.push(point);
if (this.pointArray.length == 20){
(<any>Plotly).extendTraces(this.pointArray);
this.resetPointArray();
}
但是如果我中途填充pointArray并且一段时间没有收到任何数据,我也会调用extendTraces。
我的解决方案是每秒调用一次 extendTraces()
//inside a function that is called when the page loads
window.setInterval(function() {
if (pointArray.length > 0){
(<any>Plotly).extendTraces(this.pointArray);
this.resetPointArray();
}
}, 1000);
我接收点的函数将简单地将它们连接到 pointArray 上。
//inside asynchronous function
pointArray.push(point);
我是 js 的新手,想知道我是否使用了正确的范例来完成这项任务。我看到很多关于回调和承诺的信息,我并不完全理解,但我怀疑我没有使用它们做错了什么。来自 c++,我担心两个函数,setInterval 中定义的函数和接收点的异步函数,都可以访问 pointArray 而无需任何硬编码互斥体。
你应该创建一个 debounce 函数,这基本上限制了函数的调用频率。这是下划线库中的去抖功能:
// Returns a function, that, as long as it continues to be invoked, will not
// be triggered. The function will be called after it stops being called for
// N milliseconds. If `immediate` is passed, trigger the function on the
// leading edge, instead of the trailing.
_.debounce = function(func, wait, immediate) {
var timeout, result;
var later = function(context, args) {
timeout = null;
if (args) result = func.apply(context, args);
};
var debounced = restArguments(function(args) {
if (timeout) clearTimeout(timeout);
if (immediate) {
var callNow = !timeout;
timeout = setTimeout(later, wait);
if (callNow) result = func.apply(this, args);
} else {
timeout = _.delay(later, wait, this, args);
}
return result;
});
debounced.cancel = function() {
clearTimeout(timeout);
timeout = null;
};
return debounced;
};
现在只需将 extendTraces 函数包裹在 debounce 函数周围,然后从中调用 return 的函数。
来源:https://github.com/jashkenas/underscore/blob/master/underscore.js#L887-L914
我很想将逻辑包装到它自己的 class 中,它只允许您指定
- 添加多少次后调用方法
- 在多长时间不活动后调用方法
- 调用方法
function PointHandler(flushSize, flushTime, flushCallback){
var pointArray = [];
var lastFlush = setTimeout(() => this.flush(),flushTime)
this.addPoint = function(point){
pointArray.push(point);
if(pointArray.length == flushSize){
this.flush();
}
clearTimeout(lastFlush)
lastFlush = setTimeout(() => this.flush(), flushTime);
}
this.flush = function(){
flushCallback(pointArray);
pointArray = [];
clearTimeout(lastFlush)
lastFlush = setTimeout(() => this.flush(), flushTime);
}
}
var handler = new PointHandler(10, 5000, points => console.log(points));
document.getElementById("clickme").addEventListener("click", () => handler.addPoint(new Date()));
<button id="clickme">Add point</button>
以上代码将在闲置 5 秒后或添加 10 点时调用回调。
我的回调只是 console.log
当前点,但您可以调用您的方法。
我正在异步接收数据(从每秒 0 到 100 点),这些数据将传递给高启动成本函数 extendTraces(data),该函数会更新用户界面。如果我在生成每个点时调用 extendTraces(),用户界面将变得无响应。我发现定期调用该函数并向其传递一个点数组(称为 pointArray)效率更高。
我可以跟踪有多少点被添加到 pointArray 并每添加 20 次调用 extendTraces(pointArray):
//inside asynchronous function
pointArray.push(point);
if (this.pointArray.length == 20){
(<any>Plotly).extendTraces(this.pointArray);
this.resetPointArray();
}
但是如果我中途填充pointArray并且一段时间没有收到任何数据,我也会调用extendTraces。
我的解决方案是每秒调用一次 extendTraces()
//inside a function that is called when the page loads
window.setInterval(function() {
if (pointArray.length > 0){
(<any>Plotly).extendTraces(this.pointArray);
this.resetPointArray();
}
}, 1000);
我接收点的函数将简单地将它们连接到 pointArray 上。
//inside asynchronous function
pointArray.push(point);
我是 js 的新手,想知道我是否使用了正确的范例来完成这项任务。我看到很多关于回调和承诺的信息,我并不完全理解,但我怀疑我没有使用它们做错了什么。来自 c++,我担心两个函数,setInterval 中定义的函数和接收点的异步函数,都可以访问 pointArray 而无需任何硬编码互斥体。
你应该创建一个 debounce 函数,这基本上限制了函数的调用频率。这是下划线库中的去抖功能:
// Returns a function, that, as long as it continues to be invoked, will not
// be triggered. The function will be called after it stops being called for
// N milliseconds. If `immediate` is passed, trigger the function on the
// leading edge, instead of the trailing.
_.debounce = function(func, wait, immediate) {
var timeout, result;
var later = function(context, args) {
timeout = null;
if (args) result = func.apply(context, args);
};
var debounced = restArguments(function(args) {
if (timeout) clearTimeout(timeout);
if (immediate) {
var callNow = !timeout;
timeout = setTimeout(later, wait);
if (callNow) result = func.apply(this, args);
} else {
timeout = _.delay(later, wait, this, args);
}
return result;
});
debounced.cancel = function() {
clearTimeout(timeout);
timeout = null;
};
return debounced;
};
现在只需将 extendTraces 函数包裹在 debounce 函数周围,然后从中调用 return 的函数。
来源:https://github.com/jashkenas/underscore/blob/master/underscore.js#L887-L914
我很想将逻辑包装到它自己的 class 中,它只允许您指定
- 添加多少次后调用方法
- 在多长时间不活动后调用方法
- 调用方法
function PointHandler(flushSize, flushTime, flushCallback){
var pointArray = [];
var lastFlush = setTimeout(() => this.flush(),flushTime)
this.addPoint = function(point){
pointArray.push(point);
if(pointArray.length == flushSize){
this.flush();
}
clearTimeout(lastFlush)
lastFlush = setTimeout(() => this.flush(), flushTime);
}
this.flush = function(){
flushCallback(pointArray);
pointArray = [];
clearTimeout(lastFlush)
lastFlush = setTimeout(() => this.flush(), flushTime);
}
}
var handler = new PointHandler(10, 5000, points => console.log(points));
document.getElementById("clickme").addEventListener("click", () => handler.addPoint(new Date()));
<button id="clickme">Add point</button>
以上代码将在闲置 5 秒后或添加 10 点时调用回调。
我的回调只是 console.log
当前点,但您可以调用您的方法。