php - How to delay PHP function from triggering in a jQuery Ajax Loop?
问题描述
I have a PHP script which uploads a CSV temporarily. One page reload the CSV data is got from $_FILES
and converted to a JSON array.
I then iterate through the CSV Rows using $.each
.
For each row I am doing an AJAX call to a PHP function which sets some order tracking data and sends an email.
Due to email restrictions I want to add a delay between each loop iteration. However i have attempted to do this using a set time out in the JavaScript which didn't work and also attempted to add a PHP sleep function before the email gets sent.
Neither work, the emails still get sent at the same time with no delay.
It would appear all the requests I am making regardless of the delays I am adding are being processed at once.
How can I ensure the email sending is delayed?
jQuery ($csv_rows is the CSV data which was just uploaded)
<script>
// Get CSV Rows into JSON array
var csvRows = '<?php echo json_encode( $csv_rows ); ?>';
var csvRows = ( jQuery.parseJSON( csvRows ) );
// Loop through each row
$.each( csvRows, function( key, value ) {
// Split row into array exploded by comma
row = value.toString().split( ',' );
// Get column values
order = row[0];
courier = row[1];
tracking = row[2];
// AJAX
var data = {
'action': 'shd_tracking_import',
'order': order,
'courier': courier,
'tracking': tracking,
};
// Do the ajax
$.ajax({
url: ajaxurl,
type: 'POST',
data: data,
success: function( response ) {
$( '#shd-import-results p' ).hide();
if( response !== '0' ) {
$( '#shd-import-results ul' ).append( response );
importedCount = parseInt( $( '#shd-import-progress span' ).text() );
$( '#shd-import-progress span' ).text( importedCount + 1 );
} else {
$( '<p>Error importing. Please ensure CSV meets requirements.</p>' ).appendTo( '#shd-import-results' );
}
}
});
});
</script>
PHP (this is the shd_tracking_import action referenced in AJAX)
if( isset( $_POST['order'] ) && isset( $_POST['courier'] ) && isset( $_POST['tracking'] ) ) {
// Delay (due to their Office 365 limits)
usleep( 4000000 ); // 4 Seconds (usleep used as sleep cannot contain fractions, usleep is microseconds, this was 2.5 seconds hence using usleep)
// My mailing function is here (which works just not delayed)
echo 'Done';
} else {
echo '0';
}
exit;
解决方案
虽然 Piyush 的回答是正确的,但我仍然会做这个服务器时间。我理解您为什么希望看到进展,并且有一些选择。
例如:
<?php
$file = tempnam(__DIR__, 'csv-upload');
$fh = fopen($file, 'a+b');
foreach ($csv_rows as $row) {
fputcsv($fh, $row);
}
fclose($fh);
$rowCount = count($csv_rows);
$file = str_replace(__DIR__, '', $file);
?>
<script>
var csvTotal = <?= $rowCount; ?>,
csvCount = 0,
end = false
;
var looper = requestTimeout(function () {
if (end || csvCount >= csvTotal) {
clearTimeout(looper);
return;
}
$.ajax({
url: ajaxurl,
type: 'POST',
data: {'file': '<?= $file; ?>'},
success: function (response) {
response = JSON.parse(response);
if (!response.success) {
end = true;
$('<p>' + response.msg + '</p>').appendTo('#shd-import-results');
} else {
csvCount = response.msg;
$('#shd-import-progress span').text(csvCount);
}
}
});
}, 4000);
</script>
和阿贾克斯:
<?php
session_start();
ignore_user_abort(true);
set_time_limit(0);
//filename as unique key, so you can have mutiple queues at the same time
if (!isset($_POST['file'])) {
echo json_encode([
'success' => false,
'msg' => 'File name required'
]);
die();
}
$file = __DIR__ . $_POST['file'];
if (!file_exists($file)) {
echo json_encode([
'success' => false,
'msg' => 'File does not excist'
]);
die();
}
if (!isset($_SESSION['email_status'], $_SESSION['email_status'][$file])) {
$fh = fopen($file, 'rb');
$_SESSION['email_status'][$file] = 0;
while ($row = fgetcsv($fh)) {
$order = $row['order'];
$courier = $row['courier'];
$tracking = $row['tracking'];
mail();
$_SESSION['email_status'][$file]++;
//4 seconds delaye
usleep(4000);
}
fclose($fh);
unlink($file);
} else {
echo json_encode([
'success' => false,
'msg' => $_SESSION['email_status'][$file]
]);
}
对于会话,它只会启动一次电子邮件。这里的问题是,当会话/cookies被清除时,它会再次运行它,所以最好使用不同的存储机制(redis,或者写一个pid文件或其他什么),但它应该说明我是什么试图达到。
推荐阅读
- python - Django - Heroku 推送成功但得到 AttributeError(模块没有属性)
- java - 如何在java中为文件上传设置UTF-8?
- ember.js - Ember Octane:ember-g-recaptcha reCaptchaResponse 返回未定义
- php - 是否有类似于 PHP 的 setInterval () (JavaScript) 的函数?
- amazon-web-services - AWS Lex 机器人:使用户能够在页面刷新后继续对话
- javascript - 当我使用 Express 向 Heroku 提供 index.html 文件时,为什么我的 Create-React-App 不显示?
- xamarin.forms - 为什么我的列表 ObservableCollection 永远不会刷新?
- android - Firebase 自定义声明不起作用 - android
- angular - 当我从 MS Doc 正确设置 CORS 设置时出现未知服务器错误
- java - 使用 java 有没有办法从没有典型格式扩展名的网站下载图像?