我有一个长时间运行的任务(对于每次迭代中有1秒睡眠的循环)并且我想在每次迭代中更新进度条,我使用HTML5服务器发送事件但请求状态等待10秒并且在更新进度之后完成吧,这意味着它不是实时的,我应该说我在许多PC,笔记本电脑,手机......上检查了我的代码...与各种操作系统和网络浏览器。它在所有这些上工作,就在我的笔记本电脑上,Windows 7 Home Premium无法正常工作!虽然它正在使用localhost,我也在互联网上发现了一个SSE演示(SSE Demo),它也在我的笔记本电脑上工作。我很困惑!!,任何想法? 提前致谢。
查看文件(sse.php):
<?php
use yii\helpers\Html;
$this->title = Yii::t('app', 'Server-Sent Event');
$this->params['breadcrumbs'][] = $this->title;
$js = '
var es;
function startTask() {
es = new EventSource("'.Yii::$app->urlManager->createUrl('province/default/sse').'");
//a message is received
es.addEventListener("message", function(e) {
var result = JSON.parse( e.data );
addLog(result.message);
if(e.lastEventId == "CLOSE") {
addLog("Received CLOSE closing");
es.close();
var pBar = document.getElementById("progressor");
pBar.value = pBar.max; //max out the progress bar
}
else {
var pBar = document.getElementById("progressor");
pBar.value = result.progress;
var perc = document.getElementById("percentage");
perc.innerHTML = result.progress + "%";
perc.style.width = (Math.floor(pBar.clientWidth * (result.progress/100)) + 15) + "px";
}
});
es.addEventListener("error", function(e) {
addLog("Error occurred");
es.close();
});
}
function stopTask() {
es.close();
addLog("Interrupted");
}
function addLog(message) {
var r = document.getElementById("results");
r.innerHTML += message + "<br>";
r.scrollTop = r.scrollHeight;
}
$(document).on("click", "#start_task", function() {
startTask();
});
$(document).on("click", "#stop_task", function() {
stopTask();
});
';
$this->registerJs($js);
?>
<div class="clearfix"></div>
<div class="box box-solid box-primary">
<div class="box-header">
<h3 class="box-title"><?= Html::encode($this->title) ?></h3>
</div>
<div class="box-body">
<br />
<input type="button" id="start_task" value="Start Long Task" />
<input type="button" id="stop_task" value="Stop Task" />
<br />
<br />
<p>Results</p>
<br />
<div id="results" style="border:1px solid #000; padding:10px; width:300px; height:250px; overflow:auto; background:#eee;"></div>
<br />
<progress id='progressor' value="0" max='100' style=""></progress>
<span id="percentage" style="text-align:right; display:block; margin-top:5px;">0</span>
</div>
</div>
控制器文件(DefaultController):
<?php
namespace frontend\modules\province\controllers;
use Yii;
use yii\filters\AccessControl;
use yii\web\Controller;
use yii\web\BadRequestHttpException;
/**
* Default controller for the `province` module
*/
class DefaultController extends Controller
{
public function actionTestSse()
{
return $this->render('sse');
}
public function actionSse()
{
header('Content-Type: text/event-stream');
header('Cache-Control: no-cache');
for($i = 1; $i <= 10; $i++) {
$this->send_message($i, 'on iteration ' . $i . ' of 10' , $i*10);
sleep(1);
}
$this->send_message('CLOSE', 'Process complete', 100);
}
public function send_message($id, $message, $progress) {
$d = array('message' => $message , 'progress' => $progress);
echo "id: $id" . "\n\n";
echo "data: " . json_encode($d) . "\n\n";
echo "\n\n";
ob_flush();
flush();
}
}
答案 0 :(得分:0)
好的,所以在做了一些测试之后就是一个例子。
首先是控制器:
<?php
namespace app\controllers;
use Yii;
use yii\web\Controller;
use app\models\Task;
class SiteController extends Controller
{
public function actionTask() {
return $this->render('task');
}
public function actionDoTask() {
$task = Task::find()->one();
if($task === null) {
$task = new Task();
}
$task->totalIterations = 10;
$task->started = date('Y-m-d H:i:s');
$task->iteration = 0;
$task->percentage = 0;
$task->save();
for($i = 1; $i <= 10; $i++) {
sleep(1);
$task->iteration = $i;
$task->percentage = ($i * 100) / $task->totalIterations;
$task->save();
}
return 'Some Result';
}
public function actionCheckTaskProgress() {
header('Content-Type: text/event-stream');
header('Cache-Control: no-cache');
$task = Task::find()->one();
if($task !== null) {
$data = ['message' => "on iteration " . $task->iteration . " of " . $task->totalIterations, 'progress' => $task->percentage];
}
else {
$data = ['message' => "on iteration 0 of ?", 'progress' => 0];
}
echo "data: " . json_encode($data) . "\n\n";
ob_flush();
flush();
}
}
查看:
<?php
/* @var $this yii\web\View */
use yii\helpers\Html;
$this->title = 'HTML5 Server-Sent Events';
$this->params['breadcrumbs'][] = $this->title;
$js = '
var es;
var xmlHttp;
function startTask() {
// Do an async request for some result
xmlHttp = new XMLHttpRequest();
xmlHttp.onreadystatechange = function() {
if (xmlHttp.readyState == 4 && xmlHttp.status == 200) {
es.close();
addLog(xmlHttp.responseText);
var pBar = document.getElementById("progressor");
pBar.value = 100;
var perc = document.getElementById("percentage");
perc.innerHTML = "100%";
perc.style.width = (Math.floor(pBar.clientWidth) + 15) + "px";
}
}
xmlHttp.open("GET", "'.Yii::$app->urlManager->createUrl('site/do-task').'", true);
xmlHttp.send(null);
setTimeout(function(){
es = new EventSource("'.Yii::$app->urlManager->createUrl('site/check-task-progress').'");
es.addEventListener("message", function(e) {
var result = JSON.parse( e.data );
if(result.progress == 100) {
es.close();
}
addLog(result.message);
var pBar = document.getElementById("progressor");
pBar.value = result.progress;
var perc = document.getElementById("percentage");
perc.innerHTML = result.progress + "%";
perc.style.width = (Math.floor(pBar.clientWidth * (result.progress/100)) + 15) + "px";
});
}, 100);
}
function addLog(message) {
var r = document.getElementById("results");
r.innerHTML += message + "<br>";
r.scrollTop = r.scrollHeight;
}
$(document).on("click", "#start_task", function() {
startTask();
});
';
$this->registerJs($js);
?>
<div class="clearfix"></div>
<div class="box box-solid box-primary">
<div class="box-header">
<h3 class="box-title"><?= Html::encode($this->title) ?></h3>
</div>
<div class="box-body">
<br />
<input type="button" id="start_task" value="Start Long Task" />
<br />
<br />
<p>Results</p>
<br />
<div id="results" style="border:1px solid #000; padding:10px; width:300px; height:250px; overflow:auto; background:#eee;"></div>
<br />
<progress id='progressor' value="0" max='100' style=""></progress>
<span id="percentage" style="text-align:right; display:block; margin-top:5px;">0</span>
</div>
</div>
我的结果: