2012-05-15 107 views
2

我正在嘗試與一個編碼相當糟糕,速度非常慢的網站進行交互。我將舉例說明我遇到的問題:評估內例外

在此網頁上有2個選擇框,第一個用於選擇一個國家/地區,onchange將AJAX請求發送到Web服務器返回城市列表。此列表用於填充第二個選擇框。現在問題是我可以使用phanomtjs頁面對象中的評估函數遍歷第一個選擇框並選擇正確的選項。但在此之後,我必須等待n秒鐘,然後再填充第二個框。目前我已經通過設置一個計時器等待25秒鐘來解決這個問題,然後從第二個盒子中選擇城市。然而,這是一個非常糟糕的解決方案。首先,25秒在所有情況下都不夠長,所以有時會超時而失敗。第二個問題是,在大多數情況下,25秒太長。

所以我必須找到一種方法來等待第二個盒子填充。起初我雖然可以在評估函數中使用setInterval來測試選擇框是否被填充。這是有效的,但是有一個問題,因爲setInterval是異步的,使用這種方法我失去了找出是否可以進行正確選擇的能力。爲了說明我的意思,下面的代碼是它是如何工作的時候,我沒有等到:

var retval = page.evaluate(function() { 
    return selectOption('select_id', 
         info['country']); 
}); 

這selectOption的是,在選擇元素迭代,直到它找到了正確的選擇元素的功能,如果它失敗它返回false,這個返回值然後被評估函數返回,所以我可以檢查它是否工作。

另一個選擇是隻在網頁上下文中用setInterval進行等待,然後如果失敗則引發異常。我嘗試過這樣做,但似乎無法捕捉到網站範圍之外的異常情況。 PhantomJS在終端中轉儲異常,但我無法攔截它。

有沒有辦法解決這個問題?或者我應該只使用固定的等待時間選項?

編輯:我試圖使用page.onError,但它似乎並沒有得到使用。

+0

你有沒有想過如何處理這個? –

回答

0

我還需要了解是否在評估函數中引發了異常。我設法通過增加另一層,僅僅在一個try-catch包裹函數來做到這一點:

// Wrap a function (func) inside a try-catch block and return 
// the exception if any. Otherwise return null. The ctx is a 
// a bucket for all the variables to be passed to func. 
var tryCatchWrapper = function(func, ctx) {   
    try { 
     funct(ctx); 
    } 
    catch(e) { 
     return e; 
    } 

    return null; 
} 

然後評估somefunction我用它這樣的:

var error = page.evaluate(tryCatchWrapper, somefunction); 
if (error) { 
    handle error... 
} 

如果我想傳遞參數func然後我使用上下文對象。有關如何將可變參數傳遞給函數的另一種方法,請查看以下問題:"JavaScript variable number of arguments to function"