2014-07-25 55 views
1

我尝试用sinon.js来模拟服务器,并用jQuery.ajax来调用它。但我无法让它工作。sinon.js 1.10,jquery 2.1和同步请求

下面的代码:

$(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个日志,兴农响应请求。但jQuery永远不会调用成功回调(并且错误不会被调用)。 这就像jQuery ajax请求永远不会完成。

+0

AJAX是异步的,当您调用控制台日志时,AJAX调用仍在处理中。 –

+0

即使在选项中有'async:false'? – Magus

+0

哦,我没有看到。我不知道,异步错误是一个不好的习惯,因此我从来没有使用它。 –

回答

4

问题来自sinon.js使用jQuery 2.1: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' 
})); 

问题是兴农不会触发onload事件或使用onerror回调用于同步请求。问题出在FakeXMLHttpRequest的方法setResponseBody。你可以找到这段代码:

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那样,一切正常。