Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/javascript/426.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/1/php/230.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Javascript 获取请求之间的竞争_Javascript_Php_Ajax_Api_Fetch - Fatal编程技术网

Javascript 获取请求之间的竞争

Javascript 获取请求之间的竞争,javascript,php,ajax,api,fetch,Javascript,Php,Ajax,Api,Fetch,我正在开发一个跟踪器,它应该在我们客户的网站上收集一些数据,并在网站用户离开页面时使用fetch请求将数据发送给我们的api 其想法是使用事件处理程序发送请求,但我已经读到,为了涵盖大多数浏览器,我还需要使用事件处理程序 这是我们的客户将在其网站上发布的跟踪器代码的相关部分: var requestSent = false; function submitData(element_id, url) { if (!requestSent) { v

我正在开发一个跟踪器,它应该在我们客户的网站上收集一些数据,并在网站用户离开页面时使用fetch请求将数据发送给我们的api

其想法是使用事件处理程序发送请求,但我已经读到,为了涵盖大多数浏览器,我还需要使用事件处理程序

这是我们的客户将在其网站上发布的跟踪器代码的相关部分:

var requestSent = false;
function submitData(element_id, url) {
    
    if (!requestSent) {
        
        var data = JSON.stringify({ourobject});
    
    
        fetch(url, {
           method: 'POST',
           headers: {
             'Accept': 'application/json',
             'Content-Type':'application/x-www-form-urlencoded',
           },
          body: data,})
        .then(response => response.json())
        .then((data) => {
           console.log('Hello?');
           requestSent = true;
        });
    } 
}

window.addEventListener('beforeunload', function (e) { submitData(1, "https://oursiteurl/metrics");});
window.addEventListener('unload', function(event) {submitData(1, "https://oursiteurl/metrics"); });
我在chrome上对此进行了测试,两个请求都通过了,而不仅仅是第一个成功的请求,这会导致数据库中出现重复数据

在将控制台日志放在requestSent标志设置为true的部分旁边之后,我意识到部分代码永远不会执行

如果我在“网络”选项卡中保留日志,它会说两个请求都被取消,即使数据到达我们的端点

我们的api是在Codeigniter中创建的,下面是/metrics端点

public function submit () {
      
      $this->cors();

      $response = [
          'status' => 'error',
          'message' => 'No data',
      ];
      
      $data = json_decode(file_get_contents('php://input'), true);
      if (empty($data)) {
          echo json_encode($response);exit();
      }
      // process data and do other stuff ...
Cors功能:

private function cors() {

      // Allow from any origin
      if (isset($_SERVER['HTTP_ORIGIN'])) {
          // Decide if the origin in $_SERVER['HTTP_ORIGIN'] is one
          // you want to allow, and if so:
          header("Access-Control-Allow-Origin: {$_SERVER['HTTP_ORIGIN']}");
          header('Access-Control-Allow-Credentials: true');
          header('Access-Control-Max-Age: 86400');    // cache for 1 day
      }

      // Access-Control headers are received during OPTIONS requests
      if ($_SERVER['REQUEST_METHOD'] == 'OPTIONS') {

          if (isset($_SERVER['HTTP_ACCESS_CONTROL_REQUEST_METHOD']))
              // may also be using PUT, PATCH, HEAD etc
              header("Access-Control-Allow-Methods: GET, POST, OPTIONS");         

          if (isset($_SERVER['HTTP_ACCESS_CONTROL_REQUEST_HEADERS']))
              header("Access-Control-Allow-Headers: {$_SERVER['HTTP_ACCESS_CONTROL_REQUEST_HEADERS']}");

      }

  }
编辑:

由于@CBroe建议使用,使用它消除了卸载和beforeuload事件处理程序的需要:

submitData现在看起来如下所示:

...
if (navigator.sendBeacon) {
        let beacon = navigator.sendBeacon(url, data);
        console.log( 'Beacon', beacon );
    } else { // fallback for older browsers
        if (!requestSent) {
            console.log( 'Data object from fallback', data );
            var xhr = new XMLHttpRequest();
            xhr.open("POST", url, false); // third parameter of `false` means synchronous
            xhr.send(data);
    }
 ... 
这样做只允许我保留beforeunload事件处理程序,因为它在ie和chrome上都可以工作:

 window.addEventListener('beforeunload', function (e) { submitData(1, "https://oursiteurl/metrics");});
想法是使用
beforeunload
事件处理程序发送请求,但我在这里读到,为了覆盖大多数浏览器,我还需要使用
unload
事件处理程序

这两种方法都不太适合发出AJAX/fetch请求,它们很可能在页面实际卸载时被取消

您更应该使用,这是专门为此类跟踪/保持活动状态请求而设计的


根据MDN上的浏览器兼容性列表,Internet Explorer还不支持它。如果您也需要跟踪,那么可以采用双管齐下的方法—针对支持它的浏览器的Beacon,针对IE的AJAX/fetch回退。

您应该使用什么而不是AJAX或fetch(如果你可以解决IE支持不足的问题。如果你不能解决,那么我仍然会在支持它的浏览器中使用它,并可能实现AJAX/fetch作为IE的后备方案。)@CBroe感谢您的建议,我将为支持它的浏览器切换到beacon api,但我需要它在尽可能多的浏览器上工作,所以我仍然需要使用它作为备份。@CBroe您的建议基本上解决了我的问题,我已经编辑了我的问题如果您对我的解决方案感兴趣,如果您将其作为答案发布,我将接受吧,谢谢!