2011-06-14 132 views
0

我正在使用當前代碼嘗試使用cURL異步執行兩個腳本。每個腳本都託管在不同的域上,需要大約30秒才能完成。我希望這些在後臺運行,以便頁面可以繼續加載,但它會一直掛起直到完成。我在考慮cURL的工作原理時完全錯了嗎?或者我做錯了什麼?cURL導致頁面掛起

UPDATE:

$.ajax({ 
    type : 'POST', 
    url  : 'ajax.php?mode=process', 
    data : '$url', 
    complete: function(data) 
    { 
     $('#test'+num).append('Operation successful.'); 
    } 
}); 

貨號是div的ID。它們是通過代碼生成的。所有這些都正常工作,除了cURL鎖定服務器,直到完成處理文件。

下面的代碼現在在另一個頁面上,專門用於處理從上面的jQuery ajax調用傳入的URL。

$cURLs = array(
    "script_url?param1=1&param2=2", 
    "script_url?param1=5&param2=6"); 
$result = array(); 
$mh = curl_multi_init(); 

foreach ($data as $id => $d) 
{ 
    $cURLs[$id] = curl_init(); 
    $url = (is_array($d) && !empty($d['url'])) ? $d['url'] : $d; 
    curl_setopt($cURLs[$id], CURLOPT_URL,   $url); 
    curl_setopt($cURLs[$id], CURLOPT_HEADER,   0); 
    curl_setopt($cURLs[$id], CURLOPT_RETURNTRANSFER, 1); 

    if (is_array($d)) 
    { 
      if (!empty($d['post'])) 
      { 
        curl_setopt($cURLs[$id], CURLOPT_POST,  1); 
        curl_setopt($cURLs[$id], CURLOPT_POSTFIELDS, $d['post']); 
      } 
    } 

    if (!empty($options)) 
      curl_setopt_array($cURLs[$id], $options); 

    curl_multi_add_handle($mh, $cURLs[$id]); 
} 

$running = null; 
do 
{ 
    curl_multi_exec($mh, $running); 
} while($running > 0); 

foreach($cURLs as $id => $c) 
{ 
    $result[$id] = curl_multi_getcontent($c); 
    curl_multi_remove_handle($mh, $c); 
} 

curl_multi_close($mh); 
echo "<pre>" . print_r($result, 1) . "</pre>"; 
+2

調用捲曲就像調用任何其它功能 - 腳本塊,直到函數返回。大多數功能幾乎是瞬時的,所以你不會注意到。 curl完全依賴於遠程資源的作用(以及它自己的超時參數)。 – 2011-06-14 16:29:59

回答

3

不幸的是,你的頁面將不會完成加載,直到你的腳本完成執行。即使您使用cURL Multi功能,也只能在腳本運行時使用。

如果您需要在後臺運行腳本,則必須找到其他方法,例如在數據庫中排隊下載作業,並且運行腳本以逐個檢查該隊列。

+0

考慮編寫一個PHP守護進程/任務或cron腳本來掃描隊列表以查找要下載的文件,並設計您的A.php頁面以掃描保存在表中的結果。如果需要,腳本B.php可能會每分鐘檢查一次表格。但是,您可能需要運行許多B.php任務,因爲每個B.php任務都無法同時爲多個用戶提供服務。 – 2011-06-14 17:21:32

+0

@memnoch_proxy我現在正在做這件事。將初始腳本加載所有變量並將它們保存在我的數據庫中,然後通過Ajax調用腳本。腳本將遍歷表中的每一行,處理它們並將其刪除。同時,我要在主頁上運行一個小型JS來每隔幾秒查詢一次數據庫以查看錶是否消失。當它發生時,那個缺失的表格將會完成報告。對此有何想法? – Nathan 2011-06-14 17:24:35

+0

聽起來像一個好開始 – 2011-06-14 17:29:10

0

如果您希望異步做到這一點,你需要完成輸出到你的頁面,然後使用jQuery來調用,使用捲曲加載數據的腳本。

+3

爲什麼選jQuery?爲什麼沒有圖書館?只有jQuery做ajax - 非常不真實。 – Neal 2011-06-14 16:30:54

+0

你有沒有做過這種方法?使用jQuery來運行cURL請求並使其異步執行? – Nathan 2011-06-14 16:31:03

+2

@Andrew,他暗示你有一個腳本來完成它現在所做的事情,但是客戶端頁面加載,然後用jQuery調用這個腳本。這將爲你工作,取決於你的需求。請記住,如果客戶端關閉連接,PHP將被終止,除非您在php.ini中另外配置它​​。 – Brad 2011-06-14 16:39:53

1

將此用作捲曲請求的選項。

$CURL_OPTS = array(
    CURLOPT_CONNECTTIMEOUT => 10, 
    CURLOPT_RETURNTRANSFER => true, 
    CURLOPT_TIMEOUT  => 60, 
); 
+0

這不是真正的問題在這裏。腳本本身需要大約30秒才能完成,我稱它爲71次,如果同步完成,則需要大約35分鐘才能完成。它似乎一次只能處理大約6-8個文件,將其總處理時間縮短到5分鐘左右。但是,在此期間服務器無法訪問。在處理時,不能加載其他頁面。我**需要**它是一個後臺進程,這是我_thought_ cURL會爲我做的。 – Nathan 2011-06-14 17:13:00

+0

這是設置超時但沒有達到任何並行性的示例。 – 2011-06-14 17:18:39

+0

我認爲你需要cron作業而不是 – 2011-06-22 17:40:16

0

我知道這是一個老帖子...但我也有類似的問題,我能避開它...不知道如果這是你的一樣,因爲你只共享的一部分你的代碼,但我會分享這個,因爲我發現很難找到正確的答案,這聽起來非常像我試圖解決:

我有一個ajax調用,它叫a.php,a .php通過cURL CLI調用b.php來在後臺處理頁面(使用PHP的exec()函數)b.php使用libcurl來刮取網站... b.php導致a.php停止響應我的ajax請求檢查刮刀的狀態。我發現原因是因爲我將刮板信息存儲到全局的$ _SESSION var中......您無法在多個位置讀取/寫入同一個會話,所以我週期性的ajax請求到a.php(這是使用與b.php上的cURL刮板相同的會話)被掛起。定期在整個cURL刮取器中使用session_write_close()會導致我的ajax請求不會掛起,因爲會話不再阻止頁面請求通過。

我很想找到了,如果這是你的掛Ajax請求的原因,直到完成捲曲處理