javascript - 将对象参数传递给setInterval

问题描述:

我已经编程了几年,但我是JavaScript新手。我试图创建一个标准线程'通知'功能的hacky版本。我正在运行一系列ajax数据请求,每个请求需要大约200毫秒才能执行,并且我需要等到它们全部完成后再执行一个操作(绘制图形)。javascript - 将对象参数传递给setInterval

我的解决方案是让每个线程在完成时增加一个全局变量。然后,我使用setTimeout创建了一个计时器,每隔100毫秒检查一次,看看是否所有线程都更新了变量,并且如果他们有,则执行该操作。

尽管有点哈克,这工作。

快进未来的几个星期,我的程序不断增加,现在我们需要的是 能够在同一页面上有多个图表,每个图表使用上述ajax请求独立管理其数据,如以及使用图形的几个不同页面。因此,我将图形代码提取到带有require.js的模块中,并定义一个执行图形化的类来隔离每个图形与其他图形,但突然间setInterval不起作用。我做了一些谷歌搜索,找到下面的文章,我有点明白...

http://www.novogeek.com/post/2010/02/08/Scope-problems-with-JavaScript-setInterval-setTimeout-Use-closures!.aspx

所以无论如何看来,当使用setInterval的“本”成为一些奇怪的原因的窗口,因此,看不到我的方法。

无论如何,我试图创造一个变种研究所遏制“这个”明确,这似乎帮助,但由于某些原因,它不喜欢过客“出师表”作为递归调用的参数。从Firebug控制台该错误消息是这样的:

失踪]后元素列表 [打破此错误]
}(9.9,[对象的对象))

下面是从一个样品我的代码:

var inst = this; 

// some code... then in a function... 
function(){ 
    inst.waitUntil(10, inst); 
} 

inst.waitUntil = function(how_many_seconds, inst){ 
    if (how_many_seconds < 0){ 
     alert("Script timed out."); 
     return; 
    } else { 
     if (inst.allSchoolsLoaded()){ 
      setTimeout("("+inst.draw+"("+inst.after+"))", 100); 
     } else { 
      var argString = "("+inst.waitUntil+"("+(how_many_seconds-0.1)+", "+inst+"))"; 
      //alert(argString); 
      setTimeout(argString, 100); 
     } 
    } 
} 

你可以假设所有提到的变量都是在类的前面定义的。

我在束手无策我在这里,任何帮助将非常感激。如果任何人都可以建议线程问题是可以避免的setInterval完全,这将是真棒更好的解决办法,否则,如果你能提出一个办法让setInterval的工作或替代功能,这将是巨大的。

jQuery可用,我不介意安装其他工具,如果他们会帮助。

提前许多感谢,

亚历

+0

那么,什么是错'VAR completedCalls = 0;函数ajaxThreadResult(){... completedCalls ++; }'然后检查'completedCalls == callsMade'? – 2012-02-24 01:24:04

+0

看到这个问题,并在那里回复:http://*.com/questions/2130241/pass-correct-this-context-to-settimeout-callback/9298306#9298306 – 2012-02-24 01:24:11

+0

是的,这实际上是我在做什么...函数allSchoolsLoaded()只是测试completedCalls == callsMade(显然具有不同的变量名称)。问题是如何每隔一段时间检查一下这个状态...... – Alex 2012-02-24 06:27:41

您正试图创建一个对象的字符串。对象的标准字符串表示形式为[object Object]。你可能也会有问题inst.waitUntil,因为它转化为函数的字符串表示(在某些(大多数?)的浏览器功能的源)。

而不是创建一个字符串,只是通过一个函数来setTimeout

setTimeout(function() { 
    inst.waitUntil(how_many_seconds-0.1, inst); 
}, 100); 

现在,里面waitUntilthis将参考inst。鉴于此,您可能能够进一步简化您的代码。

例如:

this.waitUntil = function(how_many_seconds){ 
    var self = this; 
    if (how_many_seconds < 0){ 
     alert("Script timed out."); 
     return; 
    } else { 
     var callback = function() { 
      self.waitUntil(how_many_seconds-0.1); 
     }; 

     if (this.allSchoolsLoaded()){ 
      callback = function() { 
       self.draw(self.after); 
      }; 
     } 
     setTimeout(callback, 100); 
    } 
}; 
+0

:-)我们写了同样的东西,很抱歉,但我喜欢只有一个setTimeout更多,很好! – 2012-02-24 01:38:26

+0

我记得在因特网上寻找setTimeout的例子,由于某些原因,他们没有证明你可以传递一个函数,所以我犯了和Alex一样的错误。希望我已经知道堆栈溢出,然后得到这样的答案。 ;-) – 2012-02-24 01:47:13

+0

对,我想我很困惑,并认为setInterval总是将'this'设置为'window'...非常感谢您的帮助:) – Alex 2012-02-24 06:25:19

不要使用字符串,它使用eval内部和它的坏为您的代码的性能和可维护性。取而代之的是:

if (inst.allSchoolsLoaded()){ 
    setTimeout("("+inst.draw+"("+inst.after+"))", 100); 
} else { 
    var argString = "("+inst.waitUntil+"("+(how_many_seconds-0.1)+", "+inst+"))"; 
    //alert(argString); 
    setTimeout(argString, 100); 
} 

这样做:

if (inst.allSchoolsLoaded()){ 
    setTimeout(function() { 
     inst.draw(inst.after); 
    }, 100); 
} else { 
    setTimeout(function() { 
     inst.waitUntil(how_many_seconds - 0.1); 
    }, 100); 
} 

而且,你不需要通过inst如果你正在使用的实例waitUntil方法,this背景将被设定为inst本身,因此:

inst.waitUntil = function (seconds) { 
    // `this` is now pointing at `inst` 
    // we will cache a reference to the object into a variable 
    // because anonymous function will have its own context (`this`) 
    // in the link provided in comment you can see alternatives such as using 
    // ECMAScript `bind` Function method to bind function context to certain object 
    var self = this; 
    if (seconds < 0) return alert('timeout'); 
    if (inst.allSchoolsLoaded()){ 
     setTimeout(function() { 
      self.draw(self.after); 
     }, 100); 
    } else { 
     setTimeout(function() { 
      self.waitUntil(seconds - 0.1); 
     }, 100); 
    } 
}; 
+0

感谢您的帮助:) – Alex 2012-02-24 06:48:30

张贴在这里的解决方案工作完美,谢谢你的帮助。

万一别人也有类似的需要执行多个AJAX请求,其实我偶然发现了一个jQuery的方法处理此优雅:

http://api.jquery.com/jQuery.when/

它可能需要几个“递延”对象,包括AJAX请求,并等待它们全部成功执行或其中一个失败。使用这个,我可以完全摆脱我的setInterval计时器。

干杯,

亚历