IE滞后于发送POST数据

Recently I found very strange behavior of IE8/9 when sending XHR data. I'd like to ask you if you have ever seen such behavior? Is it IE bug? How can I protect my server from "empty" request generated by IE? Here are more details:

I found out that when your page tries to send XHR data and JavaScript freezes or lags browser, IE lags sending POST data to server. To make it clear, here are steps to reproduce:

  • Create simple server which dumps POSTs received. I've used Node.JS for tests. You can find corresponding codes at the bottom of the post.

  • Open localhost:8080 in IE, open debug window and start debuging scripts with breakpoint set in line 51 of file localhost:8080

enter image description here

  • Hit Send by JQuery. You should have your javascript waiting on the breakpoint and server logged message:

    --------------------------------------
     14:04:19
     REQUEST: /
     HTTP HEADER:
      accept = text/html, application/xhtml+xml, */*
      accept-language = pl-PL
      user-agent = Mozilla/5.0 (compatible; MSIE 9.0; Windows NT 6.1; WOW64; Trident/5.0)
      accept-encoding = gzip, deflate
      host = localhost:8080
      connection = Keep-Alive
    --------------------------------------
    14:04:35
    REQUEST: /test
    HTTP HEADER:
      accept = */*
      content-type = application/json
      x-requested-with = XMLHttpRequest
      referer = http://localhost:8080/
      accept-language = pl
      accept-encoding = gzip, deflate
      user-agent = Mozilla/5.0 (compatible; MSIE 9.0; Windows NT 6.1; WOW64; Trident/5.0)
      host = localhost:8080
      content-length = 24
      connection = Keep-Alive
      cache-control = no-cache
    
  • When you release JavaScript from the breakpoint server reports incoming data by new line:

    POST: {"data1":10,"data2":123}
    

I've done the same test on Opera 12.15 and Chrome 27.0.1453.94 m and, as expected, POST data are sent immediately.

-- source codes --

Code for node.js server:

var http = require('http');
var qs = require('querystring');    
var fs = require('fs');


http.createServer(function (req, res) {
    console.log('--------------------------------------');  
    console.log(new Date().toLocaleTimeString());   
    console.log('REQUEST: ' + req.url); 
    console.log('HTTP HEADER: ');
    for (var header in req.headers) {
        console.log('  ' + header + ' = ' + req.headers[header]);
    }
    switch (req.method) {
        case 'POST':
            var body = '';
            req.on('data', function (data) {
                body += data;
            });

            req.on('end', function() {
                console.log('POST: ' + body);
            });

            res.writeHead(200, {'Content-type': 'application/json'});
            res.end(JSON.stringify({ succeeded: true, value: 'Hello world!' }));
            break;
        case 'GET':
            fs.readFile('./servertest.html', function (err, data) {
                if (err) {
                    throw err;
                }
                res.writeHeader(200, {'Content-type': 'text/html'});
                res.end(data);
            });
            break;
    }
}).listen(8080, 'localhost');

console.log('listening on localhost:8080');

Code for servertest.html:

<!DOCTYPE html>
<html>
    <head>
        <script src="http://ajax.googleapis.com/ajax/libs/jquery/1.9.1/jquery.min.js"></script>
    </head>

    <body>
        <button onclick="send()">Send by JQuery</button>
        <button onclick="sendXHR()">Send by XHR</button>
    </body>

    <script type="text/javascript">

        var _xhr;
        function sendXHR() {
            _xhr = new XMLHttpRequest();
            new XHRStateChangeListener();

            var url = '/testXHR';
            var method = 'POST';
            _xhr.open(method, url);
            _xhr.setRequestHeader("Content-Type", "application/json");
            _xhr.send(JSON.stringify({test: 'this is a test', aoawiejf:23423}));
        }

        function XHRStateChangeListener() {
            callback = function() {
                var msg;

                if (_xhr.readyState == 4 && /200|304/.test(_xhr.status)) {
                    alert('ready: ' + _xhr.responseText);
                }
            };

            _xhr.onreadystatechange = callback;
        }

        function send() {
            $.ajax({
                url: '/test',
                type: 'POST',
                data: JSON.stringify({data1: 10, data2: 123}),
                contentType: 'application/json',
                error: function(xhr, status, err) {
                    alert('Error: ' + err + '
Status: ' + status);
                },
                success: function (data) {
                    alert('succeeded! data: ' + data);
                }
            });
        }
    </script>
</html>

You are using sync-mode, right is async-mode:

replace _xhr.open(method, url); by _xhr.open(method, url, true);//Async mode

Note: Remember "onreadystatechange" is only for async-mode

the problem may also be in this function (just a guess): JSON.stringify

try sending empty data, ie: data:""