2016-03-01 35 views
2

謝謝您的閱讀。PHP:爲什麼我的防洪腳本滯後?

我有一個輸入字段,它將XMLHttpRequest中的內容發送到一個php腳本。該腳本使用字段中的POST數據查詢數據庫並返回結果。

因爲使用onkeyup調用XMLHttpRequest,所以輸入冗長的值會在短時間內發送多個調用。爲了解決這個問題,我編寫了一些創建時間戳的代碼,將它加載到會話中,休眠,然後重新檢查時間戳。如果時間戳增加,則表示後續調用已完成,腳本應中止。否則,腳本執行。這是代碼。

$micro = microtime(true); 
$_SESSION['micro'] = $micro; 
usleep(500000); // half a second 
if ($micro < floatval($_SESSION['micro'])) 
{ 
    // later call has been made, abort 
    echo 'abort'; 
    exit; 
} 
else 
{ 
    // okay to execute 
} 

該代碼似乎按預期在第一時間工作。如果我在輸入字段中添加或刪除一個或兩個字符,結果會很快顯示。

但是,如果我儘可能快地輸入12個字符,則會出現很大的延遲,有時會延長2到3秒。

我在localhost上工作,所以沒有連接問題。該查詢也非常小,從一個特定的行中抓取一個包含單個單詞的列。

我也設置XMLHttpRequest是異步的,所以也應該沒問題。

xmlhttp.open("POST","/test/",true); 

如果我刪除防洪代碼,在現場返回結果立刻打字 - 不管多少,以及如何快速I型。

這幾乎就像usleep()不斷堆疊本身或某物。

我自己想出了這個代碼,最好我可以在我的水平上做。不知道爲什麼它不像預期的那樣。

非常感謝幫助,謝謝!

+0

你試圖把'usleep(500000);'參加別的嗎? – Gogol

+0

爲什麼不檢查在客戶端腳本中鍵入的字符串的長度? – Khaleel

+0

你並沒有用php來完成延遲,因爲它是服務器端腳本。您需要延遲通過JavaScript(或您使用的任何客戶端語言)實際發送到腳本 –

回答

3

當您打開使用session_start()會話,PHP鎖定了會議文件,對同一個會話的任何後續請求,而另一個請求已經打開會被阻塞,直到會話關閉(你是完全正確的「堆疊」你嫌正在發生)。

您可以撥打session_write_close()關閉會話並釋放鎖定,但這可能無助於此情況。

發生了什麼事是每個鍵被按下時,一個請求被髮出的時間和每一個備份,而上一個完成,一旦會話被釋放的其他請求的一個打開的會話和睡覺,而這種情況持續發生直到他們全部完成。

相反,我會在Javascript中創建一個全局變量,指出請求是否正在執行。如果是,則不要發送另一個請求。

事情是這樣的:

<script> 
var requesting = false; 

$('#input').on('keyup', function() { 
    if (requesting) return ; 

    requesting = true; 
    $.ajax({ 
     url: "/url" 
    }).done(function() { 
     requesting = false; 
    }); 
} 
</script> 
+0

javascript看起來有點嚇人,但這個解釋非常有幫助。我知道我需要做什麼,絕對可以在解決方案上工作。真的非常感謝你!我喜歡Edward:P – Chibi

+0

:) - Javascript示例是jQuery,但是如果您擁有所有XMLHttpRequest內容,則只需將請求= true和請求= false放入您已有的內容即可。只要確保通過在任何函數之外聲明它就可以創建變量global。 – drew010

+0

謝謝。我最終提出了一個解決方案,雖然有點不同。但如果它不適合你,我仍然會嘗試使用這個會話。爲我節省了很多頭痛。 – Chibi

0

drew010的答案完全解釋我的問題(謝謝!)。但是他們的代碼示例,從我如何解釋(我沒有嘗試它)的過程中收集的,與我所需要的相反。如果用戶輸入「hello」,則h將被髮送,但是ello可能不會被髮送,除非結果及時返回。(很抱歉,如果這是一個錯誤的假設)

這是我想出了自己的解決方案。

<input type="text" onkeyup="textget(this.value)" /> 

<script> 
var patience; 
function ajax(query) 
{ 
    // XMLHttpRequest etc 
} 

function textget(input) 
{ 
    clearTimeout(patience); 
    patience = setTimeout(function(){ajax(input)},500); 
} 
</script> 

當在輸入字段中按下某個鍵時,它將其當前值傳遞給textget函數。如果有的話,並開始一個新的

的textget功能清除現有的計時器。

當計時器計時結束下來,它進一步傳遞值到AJAX函數來執行的XMLHttpRequest。

因爲計時器重置每次textget函數被調用時,如果一個新的呼叫計時器完成(0.5秒)之前提出的,以前的通話將被丟失,被替換爲新的。

希望這可以幫助別人。