我有一个简单的javascript函数:
$(document).ready(function(){
var request = $.ajax({
url: "read_images.php",
type: "GET",
dataType: "html"
});
request.done(function(msg) {
$("#mybox").html(msg);
document.getElementById('message').innerHTML = '';
});
request.fail(function(jqXHR, textStatus) {
alert( "Request failed: " + textStatus );
});
});
它调用的PHP脚本循环文件夹的内容,运行一些检查,并返回响应。脚本如下:
//Get all Images from server, store in variable
$server_images = scandir('../images/original');
//Remove first 3 elements, which are not correct
array_shift($server_images);
array_shift($server_images);
array_shift($server_images);
$j = 0;
for($i=0;$i<count($server_images) && $i<3000;$i++) {
$server_image = $server_images[$i];
//Make sure that the server image does not have a php extension
if(!preg_match('/.php/',$server_image)) {
//Select products_id and name from table where the image name is equal to server image name
$query = "SELECT `name`
FROM `images`
WHERE `name` = '$server_image'";
$mro_images = $db->query($query);
$mro_images_row = $mro_images->fetch();
$mro_image = $mro_images_row['name'];
//If no results are found
if(empty($mro_image)) {
$images[$j] = $server_image;
$j++;
}
}
}
如果循环限制为2000次迭代,但是如果我尝试执行例如结果是3000次迭代:
HTTP/1.1 500 Internal Server Error 31234ms
我已尝试增加php执行限制,但在与我的主持人联系后,这并没有任何效果:
不幸的是,在我们的环境中,我们没有办法将负载均衡器超时时间延长超过30秒
因此:如何重构此代码以避免达到执行时间限制?
答案 0 :(得分:2)
如果一切都适用于2000次迭代3000次迭代,请尝试增加时间限制以允许php执行更长时间。但在正常情况下,这不是一个好主意。确保你知道自己在做什么,并有充分的理由增加执行时间。
set_time_limit ( 60 );
http://www.php.net/manual/en/function.set-time-limit.php
这也可能是因为脚本耗尽了内存量。在其中创建一个包含phpinfo函数的文件,然后检查memory_limit的值。
<?php phpinfo(); ?>
然后你可以通过htaccess文件增加限制。但是再次确保您希望脚本消耗更多内存。小心。
ini_set('memory_limit', '128M'); #change 128 to suit your needs
答案 1 :(得分:1)
以下代码表示要遵循的基本逻辑。它不是经过测试的代码,不应被视为代码示例。
而不是让慢速进程变慢 - 编写JavaScript以在循环中请求更小的数据块。
即。 js可以使用while循环:
$(document).ready(function(){
var done = false,
offset = 0,
limit = 20;
while (!done) {
var url = "read_images.php?offset=" + offset + "&limit=" + limit;
$.ajax({
async: false,
url: url
}).done(function(response) {
if (response.processed !== limit) {
// asked to process 20, only processed <=19 - there aren't any more
done = true;
}
offset += response.processed;
$("#mybox").html("Processed total of " + offset + " records");
}).fail(function(jqXHR, textStatus) {
$("#mybox").html("Error after processing " + offset + " records. Error: " textStatus);
done = true;
});
}
});
请注意,在上面的示例中,强制ajax调用是同步的。通常您不想这样做,但在这个示例中,它更容易编写,并且可能更容易理解。
php代码还需要修改以期望并使用传递的get参数:
$stuff = scandir('../images/original');
$offset = $_GET['offset'];
$limit = $_GET['limit'];
$server_images = array_slice($stuff, $offset, $limit);
foreach($server_images as $server_image) {
...
}
...
$response = array(
'processed' => count($server_images),
'message' => 'All is right with the world'
);
header('Content-Type: application/json');
echo json_encode($response);
die;
通过这种方式,给定的php请求需要处理的工作量是固定的,因为要处理的数据总量增长(假设目录中的文件数量不会增长到不切实际的数字)。 / p>
答案 2 :(得分:0)
您的计数($ server_images)可能导致无限循环。
如果count()返回0,则for循环将永远不会结束。所以你需要先检查一下。
//Get all Images from server, store in variable
$server_images = scandir('../images/original');
//Remove first 3 elements, which are not correct
array_shift($server_images);
array_shift($server_images);
array_shift($server_images);
$j = 0;
if(count($server_images) > 0){
for($i=0;$i<count($server_images) && $i<3000;$i++) {
//Do something
}
}