本文介绍了Chrome / Firefox在相隔5秒的时间内发送两个POST,只需一次调用即可获取Nodejs 8.0.0服务器的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

注意:这不是预检选项,它不是favicon或其他任何类似的东西。它实际上是2 POSTS。下面的截图显示了这一点。

我的规格/版本:


  • macOS Sierra版本10.12.3

  • Chrome版本61.0.3128.0(官方版本)dev(64位) Node v8.0.0


    我有一台服务器在响应之前使用setTimeout等待10秒钟。我有一个前端向服务器发送单个POST。使用wireshark,我可以看到浏览器实际上创建了2个POST,第二个在t + 5s。服务器可以看到这两个POST并响应两者。前端只会得到第二个POST的结果。



    在下面的例子中,你会看到fetch实际上需要15秒才能完成,而不是10秒钟, d期待服务器超时。



    这个调用是CORS,只有当服务器花费超过5秒钟才能响应。



    这里发生了什么事情,我该如何阻止它?

    这是一个很小的复制品:

    server.js(与节点一起运行)

    var http = require(http); /一个计数器为requestvar计数器= 0; var服务器= http.createServer(函数(请求,响应){/ /闭合,以防止请求号码随计数器改变(function(requestNumber){console.log('Incoming :',request.method,分配号码,请求uestNumber); // CORS headers response.writeHead(200,{Content-Type:application / json,Access-Control-Allow-Methods:GET,HEAD,PUT,POST,DELETE,Access- Allow-Origin:*,Access-Control-Allow-Headers:authorization,content-type,expect,}); //立即响应选项。 if(request.method ===OPTIONS){response.end()} else {//否则模拟一个长时间运行的进程(db write whatever)setTimeout(function(){console.log('Timeout done, request number,requestNumber); response.write(JSON.stringify({number:requestNumber})); response.end();},10000); }}(counter ++));}); server.listen(8080); console.log(Server is listening);

    在前端获取调用:

      var start = new Date(); console.log('making call。Wait〜15 seconds for the result to return'); fetch('http:// localhost:8080',{headers: {Accept:'application / json','Content-Type':'application / json',},method:'post',mode:'cors',body:JSON.stringify({some:'content'}), })。then(result => result.json())。then(json => {console.log('result',json); console.log('call took:',(new Date() - ();});  



    以下是服务器,前端控制台和wireshark流量:



    这里是网络标签。您可以看到请求已停止5秒。



    测试中的一些附加笔记我已经完成:

    这发生在Chrome和Firefox中,但不是Safari浏览器。 (我在mac上,chrome版本60.0.3112.20(官方版本)dev(64位))这可能只会发生在CORS上,但还没有能够用最少的测试用例来确认。我试着用jQuery的 ajax 来查看它是否可能与提取有关,但它仍然发生。 (我会检查jQuery源代码,看看它是否仍然在后台使用xhr,因为我不确定它是否还没有移动到获取。)

    解决方案

    所以事实证明这是一个Node 8.0.0的bug,并且已经被8.1.1修复了。



    t确定了确切的错误,但它可能是其中之一: rel =nofollow noreferrer> https://github.com/nodejs/node/pull/13549




    NOTE: This isn't the preflight OPTIONS, and it isn't the favicon or anything else like that. It's actually 2 POSTS. There is a screenshot below to show this more clearly.

    My specs/versions:

    • macOS Sierra Version 10.12.3
    • Chrome Version 61.0.3128.0 (Official Build) dev (64-bit)
    • Node v8.0.0

    I have a server that uses setTimeout to wait 10 seconds before responding. I have a frontend that makes a single POST to the server. Using wireshark I'm able to see that the browser actually makes 2 POSTs, a second one at t+5s. The server sees both these POSTs and responds to both. The frontend only gets the result of the second POST.

    In the example below you will see that the fetch actually takes 15 seconds to complete, rather than the 10 seconds you'd expect from the timeout in the server.

    The call is CORS, and only happens when the server takes longer than 5 seconds to respond.

    What is going on here and how can I stop it?

    Here is a minimal reproduction:

    server.js (run this with node)

    var http = require("http");
    // A counter for the requests
    var counter = 0;
    
    var server = http.createServer(function(request, response) {
      // Closure to prevent the request number from changing with the counter.
      (function(requestNumber) {
        console.log('Incoming:', request.method, "assigning number", requestNumber);
    
        // CORS headers
        response.writeHead(200, {
          "Content-Type": "application/json",
          "Access-Control-Allow-Methods": "GET,HEAD,PUT,POST,DELETE",
          "Access-Control-Allow-Origin": "*",
          "Access-Control-Allow-Headers": "authorization,content-type,expect",
        });
    
        // Respond to options immediately.
        if (request.method === "OPTIONS") {
          response.end()
        } else {
          // Otherwise simulate a long running process (db write whatever)
          setTimeout(function() {
            console.log('Timeout done, responding to request number', requestNumber);
            response.write(JSON.stringify({ number: requestNumber }));
            response.end();
          }, 10000);
        }
      }(counter++));
    });
    
    server.listen(8080);
    console.log("Server is listening");

    Fetch call on the frontend:

    var start = new Date();
    console.log('making call. Wait ~15 seconds for the result to come back');
    fetch('http://localhost:8080', {
      headers: {
        Accept: 'application/json',
        'Content-Type': 'application/json',
      },
      method: 'post',
      mode: 'cors',
      body: JSON.stringify({ some: 'content' }),
    }).then(result => result.json()).then(json => {
      console.log('result', json);
      console.log('call took:', (new Date() - start), 'seconds');
    }).catch(err => {
      console.log('err', err);
    });

    Here is a screenshot of the server, the frontend console and the wireshark traffic:

    And here is the network tab. You can see the request is 'stalled' for 5 seconds.

    Some additional notes from testing I've done:

    This happens in chrome and firefox, but not safari. (I am on a mac, chrome Version 60.0.3112.20 (Official Build) dev (64-bit)) It's possible that this only happens with CORS, but haven't been able to confirm with a minimal test case. I tried it with jQuery's ajax to see if it was maybe fetch related but it still happened. (I will check the jQuery source to see if it's still using xhr under the hood because I'm not actually sure that it hasn't moved over to fetch.)

    解决方案

    So it turns out this was a bug with Node 8.0.0 and has been fixed by 8.1.1.

    I haven't nailed down the exact bug but it could be one of these:

    https://github.com/nodejs/node/pull/13549

    https://github.com/nodejs/node/commit/2cb6f2b281

    这篇关于Chrome / Firefox在相隔5秒的时间内发送两个POST,只需一次调用即可获取Nodejs 8.0.0服务器的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!

10-24 00:01