在间隔上调用的函数访问全局变量

时间:2018-07-27 15:24:36

标签: javascript plotly plotly.js

我正在异步接收数据(每秒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新手,想知道我是否为此任务使用了正确的范例。我看到了很多关于回调和Promise的信息,这些信息我还不太了解,但是我怀疑自己没有使用它们在做错事。来自c ++,我担心两个函数(在setInterval中定义的函数和接收点的异步函数)都可以访问pointArray而没有任何硬编码的互斥体。

2 个答案:

答案 0 :(得分:1)

您应该创建一个反跳功能,这基本上限制了该功能的调用频率。这是下划线库中的去抖动功能:

this.state.previousMarker.infowindow = false

现在,只需将您的extendTraces函数包装在debounce函数周围,然后调用从其返回的函数即可。

来源:https://github.com/jashkenas/underscore/blob/master/underscore.js#L887-L914

答案 1 :(得分:1)

我很想将逻辑包装到自己的类中,该类只允许您指定

  • 调用了多少个方法之后
  • 闲置多长时间后才调用该方法
  • 调用方法

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当前点,但是您可以调用您的方法。