2017-09-13 272 views
1

目前,我試圖調用一個名爲'sniffer.php'的PHP文件。 我正在做這個異步使用javascript到一個PHP文件。我目前遇到的問題是,在PHP代碼中,我隨機添加了一個睡眠函數(以加載頁面的方式運行)。這個問題是兩個或更多的函數調用該頁面,它仍然等待,直到其中一個頁面完成,然後停止啓動另一個請求。 EG:一人睡5秒,另一人睡6秒。第一個在5秒內完成,下一個在11秒完成。我正在尋找的是5秒內完成的,而下一個完成後的一秒鐘。我不確定是否只是「睡眠」引起問題,或者因爲睡眠而導致文件被「鎖定」。多個HTTP請求到單個文件

感謝您的任何幫助/反饋。

我的PHP文件看起來是這樣的:

$c = rand(2,10); 
sleep($c); 
$html .= $c; 
echo json_encode(array('html'=>$html,'status'=>1)); 
exit; 

我的JavaScript類如下所示:

var path = '/'; 

var polling = { 
    add : function(name, obj) { 
     this[name] = new xAjax(obj); 
     return this; 
    } 
}; 

function xAjax(options) { 

    var consti = { 
    }; 
    var defaults = { 
     url: path + 'sniffer.php', 
     method: 'POST', 
     responseType: 'json', 
     async: true, 
     timeout: 30000, 
     success: function(response) {console.log(response);}, 
     done: function() {}, 
     beforeSend: function() {}, 
     error: function(e) {console.log(e);}, 
     abort: function() {} 
    }; 
    var settings = Object.assign({}, defaults, options, consti); 
    var xhr = null; 

    this.run = function() { 
     xhr = new XMLHttpRequest(); 

     settings.beforeSend(); 
     xhr.responseType = settings.responseType; 
     xhr.open(settings.method, settings.url, settings.async); 
     xhr.timeout = settings.timeout; 
     xhr.onreadystatechange = function() { 
      if (xhr.readyState == XMLHttpRequest.DONE) { 
       if (xhr.status === 200) { 
        settings.success(xhr.response); 
       } else { 
        settings.error(xhr.response); 
       } 
       settings.done(); 
       xhr = null; 
      } 
     }; 
     xhr.send(); 
     return this; 
    }; 

    this.abort = function() { 
     xhr.abort(); 
     xhr = null; 
     settings.abort(); 
     return this; 
    }; 

    this.isRunning = function() { 
     return xhr != null; 
    }; 

    this.set = function(options) { 
     settings = Object.assign({}, defaults, options, consti); 
     return this; 
    }; 
} 

我的創作/打電話到sniffer.php:

polling.add('x'); 
polling.x.run(); 
polling.add('y'); 
polling.y.run(); 
+1

PHP會話鎖定併發請求。檢查你是否在你的PHP代碼中啓動任何會話,這將解釋它。 – jorgonor

+0

不幸的是,睡眠會延遲當前會話的執行,而不僅僅是當前的請求。 – ADyson

+0

你說得對。我正在開始一個會議。我假設沒有辦法繞過這一點。如果它是睡眠以外的東西(EG SQL進程),它仍然會話鎖定? – Deadweight

回答

1

這正因爲會議而發生。如果腳本需要時間,它會在有或沒有睡眠的情況下發生。

當您開始會話時會發生什麼? PHP必須確保會話數據是最新的,並且不會改變,它還必須確保它所更改的數據在下次執行時可用。

因此,如果一個腳本試圖在其他地方打開會話的時候,會有一個鎖,因爲第一個腳本可能會很好地改變會話信息。一旦第一個腳本關閉了會話,下一個腳本就可以保留它並繼續。

您可以撥打session_write_close()關閉會話進行寫入,從而刪除鎖定。當會話關閉時,它的值仍然可以被訪問,但是它會是任何後續腳本改變任何內容之前的值(如果你的第二個腳本在第一個腳本結束之前改變了某些內容,它將不會被知道)。另外,如果你寫新的數據會話,它不會被保存...

documentation

後腳本終止而不 需要調用session_write_close(會話數據通常存儲)但由於會話數據被鎖定爲 以防止併發寫入,因此只有一個腳本可以隨時在會話 上運行。

而且好像你是不是唯一的一個:

你可以開心有趣調試它與睡眠)什麼(如果 你有一個會話仍然有效。例如,一個頁面發出ajax請求,其中ajax請求輪詢服務器端事件(並且 可能不會立即返回)。

如果ajax函數沒有執行session_write_close(),那麼您的外部 頁面將掛起,並且在新選項卡中打開其他頁面 也會停止。

+0

這解釋了很多,謝謝。 – Deadweight