2012-07-01 50 views
1

我有這個功能,坪我的服務器在數據的具體變化:的JavaScript設置超時環路返回值

function connected() { 
    $.ajax({ 
    success : function(d) { 
     if (d.success) { 
     // return data 
     } else { 
     setTimeout(connected, 200); 
     } 
    } 
    }); 
} 

(顯然的代碼已被剝離到最低限度,使我的意圖更加清晰)

我想要做的是返回一個布爾真當它被發現,所以我可以去

if (connected()) { 
    // process data 
} 

(很明顯,數據存儲在一個全局變量。)

有什麼辦法可以做到這一點?

編輯

我可以創建一個 '暫停' 功能:

function pauseScript(ms) { 
    ms += new Date().getTime(); 
    while (new Date().getTime() < ms) {} 
} 

然後更改我的代碼要排除的setTimeout()(幷包括一些其他的東西)

function connected() { 
    var value; 
    $.ajax({ 
    async: false, 
    success : function(d) { 
     if (d.success) { 
     // set data 
      value = true; 
     } else { 
     pauseScript(200); 
     value = connected(); 
     } 
    } 
    }); 
    return value; 
} 

然而,這感覺有點哈克!

+3

歡迎來到**異步**的美妙世界!你不能那樣做。 – SLaks

+3

爲什麼我不能評論評論? –

+0

這不是想法!沒有什麼是不可能的! –

回答

2

做這件事最好應繼續在異步模式:

function connected(callback) { 
    $.ajax({ 
    success : function(d) { 
     if (d.success) { 
     callback(); 
     } else { 
     setTimeout(function() { 
      connected(callback); 
     }, 200); 
     } 
    } 
    }); 
} 

//Using : 
connected(function(){ 
    //Here i finish my scan result 
}); 

也許,我不是那麼肯定在這種情況下,你需要這個(我的意思是結合範圍)綁定: http://www.robertsosinski.com/2009/04/28/binding-scope-in-javascript/

+0

最好的部分是,在我的if語句中,我調用另一個函數,以便我可以將函數作爲回電話!謝謝! –

1

如果您的瀏覽器支持JavaScript 1.7或更高版本(在撰寫本文時,我認爲只有Gecko瀏覽器可以),那麼您可以利用生成器來完成此操作。讓我們先來讓你的connect功能異步(和更簡單的用於測試):

function connectAsync(callback) { 
    // Pretend we always succeed after a second. 
    // You could use some other asynchronous code instead. 
    setTimeout(callback, 1000, true); 
} 

現在換你調用代碼到一個函數。 (必須在功能上)

function main() { 
    console.log("Connecting..."); 
    if(!(yield connect())) { 
     console.log("Failed to connect."); 
     yield; return; 
    } 
    console.log("Connected."); 
    yield; 
} 

請注意所有的yield到處。這是魔術的一部分。當我們在每個函數退出點之前調用connectyield時,我們需要yield。我們需要定義connect。您可能需要一堆您可能想要同步的異步函數,因此我們來創建一個使函數同步的函數。

function synchronize(async) { 
    return function synchronous() { 
     return {func: async, args: arguments}; 
    }; 
} 

然後,我們可以用它創建connectAsyncconnect

var connect = synchronize(connectAsync); 

現在我們需要運行所有的這種神奇的功能。那就是:

function run(sync) { 
    var args = Array.prototype.slice.call(arguments); 
    var runCallback = args.length ? args[args.length - 1] : null; 
    if(args.length) { 
     args.splice(args.length - 1, 1); 
    } 
    var generator = sync.apply(window, args); 
    runInternal(generator.next()); 
    function runInternal(value) { 
     if(typeof value === 'undefined') { 
      if(runCallback) { 
       return runCallback(); 
      }else{ 
       return; 
      } 
     } 
     function callback(result) { 
      return runInternal(generator.send(result)); 
     } 
     var args = Array.prototype.slice.call(value.args); 
     args.push(callback); 
     value.func.apply(window, args); 
    } 
} 

現在你可以用這個神奇的運行main功能:

run(main); 

我要指出,這是不再可能main返回一個值。 run可以採用第二個參數:在同步功能完成時要調用的回調函數。要將參數傳遞main(比方說,123),你會這樣稱呼它:

run(main, 1, 2, 3, callback); 

如果你不想一個回調,通過nullundefined


要嘗試了這一點,你必須設置script標籤的typetext/javascript; version=1.7。 JavaScript 1.7添加了新的關鍵字(如yield),因此它是向後不兼容的,因此必須有一些方法才能將自己與舊代碼區分開來。

有關發電機的更多信息,請參閱this page on MDN。有關協程的更多信息,請參閱the article on Wikipedia

綜上所述,這是不實用的,因爲JavaScript 1.7的有限支持。此外,看到這類代碼並不常見,因此可能難以理解和維護。 我建議只使用異步樣式,如Deisss's answer中所示。不過,它是可能要做到這一點。

+0

你總結一下吧!有趣的,但在目前,這是不切實際的。雖然很好的答案! –