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

Calling JQuery function using onclick event not working as expected on Php download counter

我有一个 Php script 可以计算使用 PhpJQuery 下载文件的次数。我有一个函数 getStatus() 每秒调用一个文件 Php 并消耗大量带宽。然后我尝试仅在用户单击下载 link 时调用 getStatus(),但即使我没有收到错误,也没有按预期工作,计数器(javascript 部分)未更新实时。只有在 getStatus() 之后放置 alert() 才能正常工作。

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);
?>

download.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:

download.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 Example

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!"); returns success,注释 //alert("Thanks for downloading my files!"); returns error... 仅适用于 alert()。 ...计数器对我来说不是实时更新的...

注意事项

如您所见,由于在点击事件中添加了 setTimeout() 函数,现在仅当用户单击 link 时才会调用 getStatus() 函数。现在按预期工作。

download.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);
  });
}

感谢您花时间帮助我!

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

尝试:

 $(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;
    }

 });

为什么会出现这种情况是因为您可能误解了 Js 中的异步性作为 adeneo 提到的。所以请研究那个领域。阅读此 Async

你不能在Js中做一个真正自定义的异步函数。您最终将不得不利用 Js 中原生提供的技术,例如:

  • 设置间隔
  • 设置超时
  • 等..等..

为了快速解决问题,我可以给你这个。

 $(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 定义的 link,您的问题是您在下载计数实际增加之前获取了下载计数。

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

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

最简单的选项是:

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

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

根据 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);
  });
}