使用onclick事件调用JQuery函数在Php下载计数器上未按预期工作



我有一个Php脚本,它计算使用PhpJQuery下载文件的次数。我有一个函数getStatus(),它每秒调用一个文件Php,并且消耗大量带宽。然后,我试图只在用户点击下载链接时调用getStatus(),但即使我没有收到错误,也没有按要求工作,计数器(javascript部分)也没有实时更新。只有把alert()放在getStatus()之后,它才能工作。

index.php

<?php include($_SERVER["DOCUMENT_ROOT"] . "/php/static_download.php"); ?>
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Download Page</title>
<script src="jsc/jquery.min.js"></script>
<script src="jsc/download.js"></script>
<link rel="stylesheet" type="text/css" href="index.css">
</head>
<body>
<div class="mainbox">
<div class="box1">
<span class="title">Download</span>
</div>
<div class="cleardiv"></div>
<div class="sbar"></div>
<div class="cleardiv"></div>
<div class="box2">
<span class="row">File: <a href="files/exampleA.zip" class="link">exampleA.zip</a> downloaded <span id="item1"><?php echo $item['item1']; ?></span> times</span><br />
<span class="row">File: <a href="files/exampleB.zip" class="link">exampleB.zip</a> downloaded <span id="item2"><?php echo $item['item2']; ?></span> times</span><br />
<span class="row">File: <a href="test/test.zip" class="link">test.zip</a> this file will not be counted</span><br />
</div>
<div class="cleardiv"></div>
</div>
</body>
</html>

call_download.php

<?php    
$item['item1'] = get_download_count('exampleA.zip');
$item['item2'] = get_download_count('exampleB.zip');
if (!headers_sent()) {
header('Content-type: application/json; charset=utf-8');
}
echo json_encode($item);
?>

下载.js

$(function() {
getStatus();
});
function getStatus() {
$.getJSON('/php/call_download.php', function(data) {
$('#item1').html(data.item1);
$('#item2').html(data.item2);
});
setTimeout("getStatus()",1000);
}

正如你所看到的,getStatus()函数每隔一秒就会被调用一次,所以我尝试修改download.js如下:

下载.js

$(document).ready(function() {
$(document).on('click','.link',function(event) {
getStatus();
alert("Thanks for downloading my files!");
});
});
function getStatus() {
$.getJSON('/php/call_download.php', function(data) {
$('#item1').html(data.item1);
$('#item2').html(data.item2);
});
}

由于一些我无法理解的原因,在getStatus()之后添加alert()使计数器工作。。。如果我评论alert()停止工作。

Php示例

PS:我测试了getStatus(),惊讶地发现了一件奇怪的事情。。。

$(document).ready(function() {
$(document).on('click','.link',function(event) {
getStatus();
alert("Thanks for downloading my files!");
});
});
function getStatus() {
$.getJSON('/php/call_download.php', function(data) {
$('#item1').html(data.item1);
$('#item2').html(data.item2);
alert("success");
}).done(function(getStatus) {
alert("success");
}).fail(function(getStatus) {
alert("error");
}).always(function(getStatus) {
alert("complete");
});
}

其中alert("Thanks for downloading my files!");返回success,注释//alert("Thanks for downloading my files!");返回error。。。仅适用于alert()。。。。计数器对我来说不是实时更新的…

注意事项

正如您所看到的,由于在点击事件中添加了setTimeout()函数,现在只有当用户点击链接时才会调用getStatus()函数。现在工作如预期。

下载.js

$(document).ready(function() {
$.ajaxSetup({cache: false});
// $.ajaxSetup({async: false});
$(document).on('click','.link',function(event) {
setTimeout("getStatus()",1000);
});
});
function getStatus() {
$.getJSON('/test/php/call_download.php', function(data) {
$('#item1').html(data.item1);
$('#item2').html(data.item2);
});
}

谢谢你花时间帮助我!

为什么会发生这种情况,是因为您可能误解了Js中的异步性。所以请研究一下那个区域。读取此异步

您无法在Js中创建真正的自定义异步函数。您最终将不得不利用Js中本地提供的技术,例如:

  • 设置间隔
  • setTimeout
  • 等等。。等等

对于快速解决方案,我能给你的是这个。

$(document).ready(function() {
$(document).on('click','.link',function(event) {
$.getJSON('/test/php/call_download.php', function(data) {
$('#item1').html(data.item1);
$('#item2').html(data.item2);
alert("success");
}).done(function(getStatus) {
alert("success");
}).fail(function(getStatus) {
alert("error");
}).always(function(getStatus) {
alert("complete");
});
});
});

根据我在评论中的后续问题和您到call_download.php定义的链接,您的问题是下载次数在实际增加之前就已经得到了。

使请求同步(async: false)不会有任何效果(除了恶化用户体验),这只会使后续代码等待$.getJSON()完成,但您没有后续代码。

除了处理时间戳之外,call_download.php没有简单可靠的方法来知道另一个请求(增加计数器)是否完成。

最简单的选择是:

  1. 假设数据库中的计数总是需要一定的时间才能递增:$.getJSON()setTimeout()延迟与(通常)将计数写入数据库所需的时间一样长的时间,并留有一定的余量。

  2. 假设call_download.php总是在数据库中的计数递增之前从数据库中读取数据:$('#item1').html(data.item1 + 1);递增$.getJSON()的结果。

这可能是因为它触发了链接事件,需要首先保持

尝试:

$(document).on('click','.link',function(event, gotoUrl) {
if(!gotoUrl){
event.preventDefault();
getStatus(); // <-- maybe you should have a callback function to make sure you get response and only then trigger the click event
$(event.target).click(event, true);
return false;
}
});

基于Iceburg和Samuel Lindblom的回答,我最终编写了一个函数,该函数只在用户点击要下载的文件时使用setTimeout,而不再使用未来版本中不推荐使用的$.ajaxSetup({async: false});。因此可以节省大量带宽!这就是全部!谢谢

$(document).ready(function() {
$.ajaxSetup({cache: false});
// $.ajaxSetup({async: false});
$(document).on('click','.link',function(event) {
setTimeout("getStatus()",1000);
});
});
function getStatus() {
$.getJSON('/php/call_download.php', function(data) {
$('#item1').html(data.item1);
$('#item2').html(data.item2);
});
}

最新更新