簡體   English   中英

閱讀長期運行的PHP流程客戶端

[英]Read long-running PHP process client side

我想閱讀一個長期運行的php流程,該流程將在滿足條件時返回數據。

從我的研究中,我發現:

  • 長時間輪詢
  • 套接字(socket.io和node.js)
  • 棘輪

我正在努力理解並應用我的問題的實現。 我在PHP中有以下循環:

public function store(ClientImpl $a)
{
    $request = \Illuminate\Support\Facades\Request::all();
    $originateMsg = new OriginateAction('Local/' . $request['agent'] . '@auto-answer');
    $originateMsg->setContext('G-Outgoing');
    $originateMsg->setPriority('1');
    $originateMsg->setExtension($request['dial']);
    $a->send($originateMsg);

    while(true) {
        if( $a->process() ) break;
        usleep(1000);
    }

    $a->close();

    echo 'OK';
    ob_end_flush();
    flush();
}

$a->process()調用以下方法:

/**
 * Main processing loop. Also called from send(), you should call this in
 * your own application in order to continue reading events and responses
 * from ami. 
 */
public function process()
{
    $msgs = $this->getMessages();
    foreach ($msgs as $aMsg) {
        if ($this->_logger->isDebugEnabled()) {
            $this->_logger->debug(
                '------ Received: ------ ' . "\n" . $aMsg . "\n\n"
            );
        }
        $resPos = strpos($aMsg, 'Response:');
        $evePos = strpos($aMsg, 'Event:');
        if (($resPos !== false) && (($resPos < $evePos) || $evePos === false)) {
            $response = $this->_messageToResponse($aMsg);
            $this->_incomingQueue[$response->getActionId()] = $response;
        } else if ($evePos !== false) {
            $event = $this->_messageToEvent($aMsg);
            $response = $this->findResponse($event);
            if ($response === false || $response->isComplete()) {
                $this->dispatch($event);
            } else {
                $response->addEvent($event);
            }
        } else {
            // broken ami.. sending a response with events without
            // Event and ActionId
            $bMsg = 'Event: ResponseEvent' . "\r\n";
            $bMsg .= 'ActionId: ' . $this->_lastActionId . "\r\n" . $aMsg;
            $event = $this->_messageToEvent($bMsg);
            $response = $this->findResponse($event);
            $response->addEvent($event);
        }
        if ($this->_logger->isDebugEnabled()) {
            $this->_logger->debug('----------------');
        }
    }
}

然后$a->process()堆疊事件消息,以讀取這些消息,我創建了IEventListener的實現, IEventListener調用$a->process()時,該實現也稱為“幕后”。

class VoipEventStart implements IEventListener
{
    public function handle(EventMessage $event)
    {
        $a = $event->getKeys();

        if( ($a['event'] == "Hangup" || $a['event'] == "HangupRequest") && strpos($a['channel'], 'SIP/') !== FALSE)
        {
            return true;
        }

        return false;
    }
}

當用戶正在進行通話時,該處理方法會從Asterisk PBX系統讀取事件。 這意味着過程循環將一直持續到調用持續。

在瀏覽器看起來沒有加載/等待狀態的情況下,如何執行此客戶端?

您可以使用“ 服務器發送事件”或某些套接字實現,但是對於最簡單的方法來說,長輪詢策略可能效果很好。

為此,請從客戶端發送普通的AJAX請求,並使服務器僅在滿足條件時才返回。 它可以像更改服務器端代碼一樣簡單,如下所示:

while(true) {
    if( $a->process() ) break;
    usleep(1000);
}
echo 'OK';
ob_end_flush();
flush();

並且客戶端應該向啟動上述循環的PHP文件發送一個簡單的GET請求。 這樣,當響應返回到該請求時,您知道process()返回true。

客戶端代碼可能如下所示:

<div>Call status: <span id="status">In call</span></div>
<script>
  $.get('/check_call_status.php?callerId=123', function(response) {
    if(response === 'OK') {
      $('#staus').html('finished');
    }
  });
</script>

當然,處理超時可能更復雜。 例如,如果在給定的時間段內對長輪詢請求無響應,請重新啟動它-即中止該請求並再次發送以避免客戶端或服務器超時。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM