js 1.10, jquery 2.1和同步请求

sinon.js 1.10, jquery 2.1 and synchronous request

本文关键字:同步 请求 jquery js      更新时间:2023-09-26

我尝试用sinon.js模拟服务器,并使用jQuery.ajax调用它。但是我不能让它工作。

代码如下:

$(function() {
  var server = sinon.fakeServer.create();
  server.respondWith('POST', '/some/test', [200, { 'Content-Type' : 'application/json'}, JSON.stringify({
    id : 'test',
    value : 'test'
  })]);
  var success = sinon.spy(),
      error = sinon.spy();
  jQuery.ajax({
    url : '/some/test',
    async : false,
    type : 'POST',
    data : JSON.stringify({
      test : 'test'
    }),
    contentType : 'application/json',
    success : success,
    error : error,
  });
  console.log(server.requests[0].status);
  console.log(server.requests[0].method);
  console.log(server.requests[0].url);
  console.log(server.requests[0].requestBody);
  console.log(success.called);
  console.log(error.called);
  server.restore();
});

如果您尝试这段代码,您将看到这样的输出:

200
POST
/some/test
{"test":"test"}
false
false

根据前4条日志,sinon响应请求。但是jQuery从来没有调用成功回调(错误也没有调用)。这就像jQuery的ajax请求永远不会结束。

问题来自jQuery 2.1的sinon.js: https://github.com/cjohansen/Sinon.JS/issues/510

jQuery 2.1的同步ajax请求如下:
var req = new XMLHttpRequest();
req.open('POST', '/some/test', false); 
req.setRequestHeader('Content-Type', 'application/json');
req.onload = function() {
  console.log('success');
};
req.onerror = function() {
  console.log('error');
};
req.send(JSON.stringify({
  test : 'test'
}));

问题是Sinon不会触发同步请求的onload或onerror回调。问题出在FakeXMLHttpRequestsetResponseBody方法上。您可以找到以下代码:

if (this.async) {
    this.readyStateChange(FakeXMLHttpRequest.DONE);
} else {
    this.readyState = FakeXMLHttpRequest.DONE;
}

在最近的浏览器中,即使是同步请求,XmlHttpRequest也会触发回调。所以这段代码应该这样修改:

if (!this.async) {
    this.readyState = FakeXMLHttpRequest.DONE;
}
this.readyStateChange(FakeXMLHttpRequest.DONE);

如果你像这样修补sinon.js,一切都会正常。