我想在我的网站上创建一个进度条,该进度条跟踪PHP脚本的执行。
PHP脚本与Google API建立了许多连接,并将其接收的数据存储在数据库中。有时,此过程可能需要一分钟。
PHP脚本位于ajax/integrations-ajax.php
文件中,并通过发送的GET AJAX请求启动,如果在网站上单击#link
按钮。下面是该请求的jQuery代码:
$('#link').on('click', function () {
var interval = setInterval(trackStatus, 1000);
$.getJSON('ajax/integrations-ajax.php', {action: 'link'}).done(function (json) {
if (json.result == true) {
showMessage('The account is successfully linked.', 'success');
} else {
showMessage('There is an error happened.', 'danger');
}
})
});
此#link
按钮还设置了每秒触发trackStatus
功能的时间间隔:
function trackStatus() {
$.getJSON('ajax/status-ajax.php', {
action: 'status'
}).done(function (json) {
console.log(json.status);
});
}
如您所见,trackStatus
函数将GET AJAX请求发送到ajax/status-ajax.php
文件,并且应该每秒在浏览器控制台中显示状态。
为了在服务器上实现跟踪功能,我在ajax/integrations-ajax.php
文件中制作了PHP脚本,以将状态存储在数据库中。您可以在下面看到其代码:
<?php
if(!is_ajax_request()) { exit; }
$action = isset($_GET['action']) ? (string) $_GET['action'] : '';
if ($action == 'link') {
set_status_in_database(0);
// some execution code;
set_status_in_database(1);
// some execution code;
set_status_in_database(2);
// some execution code;
set_status_in_database(3);
// some execution code;
echo json_encode(['result' => true ]);
}
并创建了另一个PHP文件axax/status-ajax.php
,该文件可以从数据库中恢复状态:
<?php
if(!is_ajax_request()) { exit; }
$action = isset($_GET['action']) ? (string) $_GET['action'] : '';
if ($action == 'status') {
$return['result'] = get_status_from_database();
echo json_encode($return);
}
但是请求似乎无法同时工作。直到未收到完成trackStatus
脚本的响应,我才能收到ajax/integrations-ajax.php
函数的响应。
那么,是否有可能同时执行请求?还是要实现跟踪功能,我需要重新考虑整个方法?
提前感谢您的帮助!
更新 谢谢大家的指教!特别是@Keith,因为他的解决方案最简单且有效。我在脚本的开头放置了session_write_close()函数,一切正常:
<?php
if(!is_ajax_request()) { exit; }
$action = isset($_GET['action']) ? (string) $_GET['action'] : '';
if ($action == 'link') {
session_write_close();
set_status_in_database(0);
// some execution code;
set_status_in_database(1);
// some execution code;
set_status_in_database(2);
// some execution code;
set_status_in_database(3);
// some execution code;
echo json_encode(['result' => true ]);
}
答案 0 :(得分:2)
建议您尝试使用EventSource。这是一个例子。
PHP
<?php
header('Content-Type: text/event-stream');
// recommended to prevent caching of event data.
header('Cache-Control: no-cache');
function send_message($id, $message, $progress) {
$d = array('message' => $message , 'progress' => $progress);
echo "id: $id" . PHP_EOL;
echo "data: " . json_encode($d) . PHP_EOL;
echo PHP_EOL;
ob_flush();
flush();
}
for($i=0; $i<4; $i++){
set_status_in_database($i);
// some execution code;
send_message($i, "set status in database " . $i + 1 . " of 3' , $i*4);
sleep(1);
}
send_message('CLOSE', 'Process complete');
?>
JavaScript
var es;
function startTask() {
es = new eventSource('ajax/status-ajax.php');
es.addEventListener('message', function(e) {
var result = JSON.parse(e.data);
console.log(result.message);
if(e.lastEventId == 'CLOSE') {
console.log('Received CLOSE closing');
es.close();
showMessage('The account is successfully linked.', 'success');
} else {
$('.progress').css("width", result.progress + '%');
}
});
es.addEventListener('error', function(e) {
console.log('Error occurred', e);
es.close();
});
}
function stopTask() {
es.close();
console.log('Interrupted');
}
$('#link').on('click', function(e) {
e.preventDefault();
startTask($(this));
});
参考:
希望对您有用。
答案 1 :(得分:2)
虽然PHP可以毫无问题地处理并发请求,但确实要序列化的一个区域是Session,基本上,在请求期间,PHP会为该用户在SESSION上设置排他锁。 IOW:当此锁打开时,来自同一用户的其他请求将不得不等待。通常这不是问题,但是如果您的请求运行时间较长,它将阻止其他请求,例如AJax请求等。
默认情况下,PHP将在写入会话数据,然后结束请求。但是,如果您确定不再需要写入任何会话数据,则调用session_write_close
将更早地释放锁。
更多信息在这里-> http://php.net/manual/en/function.session-write-close.php
答案 2 :(得分:1)
php逻辑和JavaScript语法似乎都不错;但是,以最少的php代码示例为例,假定它的资源过多。 MySQL可能很忙,这就是获取状态可能等待MySQL的原因。
我通过将更新状态 写入文件而不是争用数据库资源来解决这个问题。
答案 3 :(得分:0)
由于您考虑使用其他方法,因此让我推荐GraphQL作为数据库上的薄层/ api。
那里有很多Php解决方案,例如Siler。寻找一个具有subscriptions的功能(并非所有功能都可以),因为这是您要寻找的功能。订阅用于创建网络套接字(您的PHP和Javascript之间的流),从而将与状态相关的所有通信减少到一个呼叫。
是的,这可能是“向大炮射击”,但也许您还有其他东西在飞来飞去,那么也许值得考虑。 fantastic document有一个有趣的概念。您将可以在resolver functions中重用大多数与数据库相关的Php。