2012-02-24 161 views
0

我已經編程了幾年,但我是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://stackoverflow.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

回答

3

您正試圖創建一個對象的字符串。對象的標準字符串表示形式爲[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

1

不要使用字符串,它使用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

0

張貼在這裏的解決方案工作完美,謝謝你的幫助。

萬一別人也有類似的需要執行多個AJAX請求,其實我偶然發現了一個jQuery的方法處理此優雅:

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

它可能需要幾個「遞延」對象,包括AJAX請求,並等待它們全部成功執行或其中一個失敗。使用這個,我可以完全擺脫我的setInterval計時器。

乾杯,

亞歷