我有两个ajax调用。第一个调用是读取文件并将其保存到DB(mysql)中,并在for循环的底部设置一个" status"的会话变量。喜欢间隔。 第二个调用返回会话变量。
这是我的javascript代码:
var interval = null;
function test(data) {
var i = 0;
interval = setInterval(function () {
$.ajax({
url: '/admin/movies/progress',
type: "GET",
async: true,
dataType: "text",
success: function (data) {
console.log(data);
$('#saveFileProgressBar').width(data[0]);
},
error: function (XMLHttpRequest, textStatus, errorThrown) {
toastr.error('error progressbar', 'Download File');
}
});
i++;
if(i == 5){
clearInterval(interval);
}
}, 500);
$.ajax({
url: '/admin/movies/1',
type: "GET",
async: true,
dataType: "text",
success: function (data) {
console.log(data);
},
error: function (XMLHttpRequest, textStatus, errorThrown) {
toastr.error('error', 'Download File');
}
});
}
这是我的laravel 5.4代码:
// Mapped to mysite.com/admin/movies/progress
public function getProgress() {
return Response::json(array(Session::get('progress')));
}
// Mapped to mysite.com/admin/movies/1
public function postGenerate() {
// getting values from form (like $record_num)
Session::put('progress', 0);
Session::save(); // Remember to call save()
for ($i = 1; $i < 100; $i++) {
sleep(1);
Session::put('progress', $i);
Session::save(); // Remember to call save()
}
return "done";
}
/////// EDIT ///////
我的新PHP代码:
public function getProgress() {
$rawData = file_get_contents('plugins/elFinder-2.1.25/files/data/progressFile.json');
$cacheData = json_decode($rawData, true);
return $cacheData;
}
public function postGenerate() {
// getting values from form (like $record_num)
for ($i = 0; $i < 10; $i++) {
$data['progress'] = $i;
$fres = fopen('plugins/elFinder-2.1.25/files/data/progressFile.json', 'w');
fwrite($fres, json_encode($data));
fclose($fres);
sleep(1);
}
return "true";
}
我的javascript代码:
var interval = null;
function test() {
var i = 0;
interval = setInterval(function () {
$.ajax({
url: '/admin/movies/progress',
type: "GET",
async: true,
dataType: "text",
success: function (data) {
console.log(data);
$('#saveFileProgressBar').width(data.progress);
},
error: function (XMLHttpRequest, textStatus, errorThrown) {
toastr.error('Es ist ein Fehler aufgetreten beim Auslesen der Datei', 'Download File');
}
});
i++;
if(i == 5){
clearInterval(interval);
}
}, 500);
$.ajax({
url: '/admin/movies/1',
type: "GET",
async: true,
dataType: "text",
success: function (data) {
console.log(data);
},
error: function (XMLHttpRequest, textStatus, errorThrown) {
toastr.error('Es ist ein Fehler aufgetreten beim Auslesen der Datei', 'Download File');
}
});
}
答案 0 :(得分:1)
而不是使用会话使用常规文件。在脚本完成之前,会为每个唯一会话锁定会话文件。所以它不能并行运行。您可以做的是将数据存储在普通文件中并访问它。
从缓存文件中读出
$rawData = file_get_contents('data/progressFile.json');
$cacheData = json_decode($rawData, true);
写得像
$data['progress'] = 100;
$fres = fopen('data/progressFile.json', 'w');
fwrite($fres, json_encode($data));
fclose($fres)
您可以将json数据结构用于所有会话并解析以获取特定进度数据,或者您可以将单独的文件用于ech进度数据。如果您使用一个大文件,则可能需要使用flock()
在写入期间锁定文件。
答案 1 :(得分:1)
<强>请强>
<强>响应强>
您好,
我刚刚对您的脚本进行了测试,响应在上面的图片中。第一个图像是AJAX请求列表。绿色的请求已完成,灰色请求仍在进行中。第二个图像按请求完成的顺序显示呼叫响应的日志(第一个完成的请求显示在顶部,依此类推......)。
图片中1 指的是第一次AJAX通话(当然我将其重命名为 / set-progress 而不是 /管理/电影/ 1 强>)。随后的第二次AJAX调用标记为 2 - 6 和 / progress = / admin / movies / progress 。
我认为你的问题是后续(第二次调用)请求在第一个请求完成之前没有运行。从我的结论来看,我认为是假的。显然,我们可以看到第一个请求仍在等待,而其他请求已完成。所以,我们可以说你的请求是并行运行的。
对于您的情况,只有一个问题(最不可能;只要您有足够的资源来处理小请求),也就是说,您的服务器资源不足。意味着它没有足够的内存来提供第二次调用。由于第一次通话经过并且服务器资源不足,因此无法处理更多请求,从而阻止第二次通话,直到首次请求已经完成了。因此,第一次调用或任何其他正在运行的任务/进程/请求正在消耗您的服务器资源,因此阻止了进一步的请求。
阅读有关文件被锁定的注释和上一个答案,以便并行请求无法发送到服务器或服务器无法接受并行请求。这个陈述也是不正确的。每次更新会话文件时会锁定会话文件,但这与浏览器一次发送多个请求没有任何关系。
如果文件不可用/在任何请求期间不存在, Laravel 只需会引发500错误。下面的附件图显示了案例的答案,文件不可用。
如果文件在写入时被锁定,则响应(进行呼叫)只是空的。这意味着,该文件存在但其内容目前不可用。下图显示了样本响应。
如果此答案不满足您,请点击这些链接。看看他们是否有帮助。 Link 1和Link 2。
我的测试环境: