mirror of
https://github.com/Hopiu/angular.js.git
synced 2026-03-16 23:30:23 +00:00
feat($browser): JSONP error handling
since we don't know if the error was due to a client error (4xx) or server error (5xx), we leave the status code as undefined.
This commit is contained in:
parent
4dc9e6416a
commit
6f8904e027
2 changed files with 93 additions and 23 deletions
|
|
@ -100,12 +100,19 @@ function Browser(window, document, body, XHR, $log) {
|
|||
outstandingRequestCount ++;
|
||||
if (lowercase(method) == 'json') {
|
||||
var callbackId = ("angular_" + Math.random() + '_' + (idCounter++)).replace(/\d\./, '');
|
||||
var script = self.addJs(url.replace('JSON_CALLBACK', callbackId));
|
||||
window[callbackId] = function(data){
|
||||
window[callbackId] = function(data) {
|
||||
window[callbackId].data = data;
|
||||
};
|
||||
|
||||
var script = self.addJs(url.replace('JSON_CALLBACK', callbackId), null, function() {
|
||||
if (window[callbackId].data) {
|
||||
completeOutstandingRequest(callback, 200, window[callbackId].data);
|
||||
} else {
|
||||
completeOutstandingRequest(callback);
|
||||
}
|
||||
delete window[callbackId];
|
||||
body[0].removeChild(script);
|
||||
completeOutstandingRequest(callback, 200, data);
|
||||
};
|
||||
});
|
||||
} else {
|
||||
var xhr = new XHR();
|
||||
xhr.open(method, url, true);
|
||||
|
|
@ -452,7 +459,7 @@ function Browser(window, document, body, XHR, $log) {
|
|||
* @description
|
||||
* Adds a script tag to the head.
|
||||
*/
|
||||
self.addJs = function(url, domId) {
|
||||
self.addJs = function(url, domId, done) {
|
||||
// we can't use jQuery/jqLite here because jQuery does crazy shit with script elements, e.g.:
|
||||
// - fetches local scripts via XHR and evals them
|
||||
// - adds and immediately removes script elements from the document
|
||||
|
|
@ -465,6 +472,15 @@ function Browser(window, document, body, XHR, $log) {
|
|||
script.type = 'text/javascript';
|
||||
script.src = url;
|
||||
if (domId) script.id = domId;
|
||||
|
||||
if (msie) {
|
||||
script.onreadystatechange = function() {
|
||||
/loaded|complete/.test(script.readyState) && done && done();
|
||||
}
|
||||
} else {
|
||||
if (done) script.onload = script.onerror = done;
|
||||
}
|
||||
|
||||
body[0].appendChild(script);
|
||||
|
||||
return script;
|
||||
|
|
|
|||
|
|
@ -87,27 +87,81 @@ describe('browser', function(){
|
|||
|
||||
describe('xhr', function(){
|
||||
describe('JSON', function(){
|
||||
it('should add script tag for request', function() {
|
||||
var callback = jasmine.createSpy('callback');
|
||||
var log = "";
|
||||
browser.xhr('JSON', 'http://example.org/path?cb=JSON_CALLBACK', null, function(code, data){
|
||||
log += code + ':' + data + ';';
|
||||
});
|
||||
browser.notifyWhenNoOutstandingRequests(callback);
|
||||
expect(callback).not.toHaveBeenCalled();
|
||||
expect(scripts.length).toEqual(1);
|
||||
var script = scripts[0];
|
||||
var url = script.src.split('?cb=');
|
||||
expect(url[0]).toEqual('http://example.org/path');
|
||||
expect(typeof fakeWindow[url[1]]).toEqual($function);
|
||||
fakeWindow[url[1]]('data');
|
||||
expect(callback).toHaveBeenCalled();
|
||||
expect(log).toEqual('200:data;');
|
||||
expect(scripts).toEqual(removedScripts);
|
||||
expect(fakeWindow[url[1]]).toBeUndefined();
|
||||
var log;
|
||||
|
||||
function callback(code, data) {
|
||||
log += code + ':' + data + ';';
|
||||
}
|
||||
|
||||
beforeEach(function() {
|
||||
log = "";
|
||||
});
|
||||
|
||||
|
||||
// We don't have unit tests for IE because script.readyState is readOnly.
|
||||
// Instead we run e2e tests on all browsers - see e2e for $xhr.
|
||||
if (!msie) {
|
||||
|
||||
it('should add script tag for JSONP request', function() {
|
||||
var notify = jasmine.createSpy('notify');
|
||||
browser.xhr('JSON', 'http://example.org/path?cb=JSON_CALLBACK', null, callback);
|
||||
browser.notifyWhenNoOutstandingRequests(notify);
|
||||
expect(notify).not.toHaveBeenCalled();
|
||||
expect(scripts.length).toEqual(1);
|
||||
var script = scripts[0];
|
||||
var url = script.src.split('?cb=');
|
||||
expect(url[0]).toEqual('http://example.org/path');
|
||||
expect(typeof fakeWindow[url[1]]).toEqual($function);
|
||||
fakeWindow[url[1]]('data');
|
||||
script.onload();
|
||||
|
||||
expect(notify).toHaveBeenCalled();
|
||||
expect(log).toEqual('200:data;');
|
||||
expect(scripts).toEqual(removedScripts);
|
||||
expect(fakeWindow[url[1]]).toBeUndefined();
|
||||
});
|
||||
|
||||
|
||||
it('should call callback when script fails to load', function() {
|
||||
browser.xhr('JSON', 'http://example.org/path?cb=JSON_CALLBACK', null, callback);
|
||||
var script = scripts[0];
|
||||
expect(typeof script.onload).toBe($function);
|
||||
expect(typeof script.onerror).toBe($function);
|
||||
script.onerror();
|
||||
|
||||
expect(log).toEqual('undefined:undefined;');
|
||||
});
|
||||
|
||||
|
||||
it('should update the outstandingRequests counter for successful requests', function() {
|
||||
var notify = jasmine.createSpy('notify');
|
||||
browser.xhr('JSON', 'http://example.org/path?cb=JSON_CALLBACK', null, callback);
|
||||
browser.notifyWhenNoOutstandingRequests(notify);
|
||||
expect(notify).not.toHaveBeenCalled();
|
||||
|
||||
var script = scripts[0];
|
||||
var url = script.src.split('?cb=');
|
||||
fakeWindow[url[1]]('data');
|
||||
script.onload();
|
||||
|
||||
expect(notify).toHaveBeenCalled();
|
||||
});
|
||||
|
||||
|
||||
it('should update the outstandingRequests counter for failed requests', function() {
|
||||
var notify = jasmine.createSpy('notify');
|
||||
browser.xhr('JSON', 'http://example.org/path?cb=JSON_CALLBACK', null, callback);
|
||||
browser.notifyWhenNoOutstandingRequests(notify);
|
||||
expect(notify).not.toHaveBeenCalled();
|
||||
|
||||
scripts[0].onerror();
|
||||
|
||||
expect(notify).toHaveBeenCalled();
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
it('should normalize IE\'s 1223 status code into 204', function() {
|
||||
var callback = jasmine.createSpy('XHR');
|
||||
|
||||
|
|
|
|||
Loading…
Reference in a new issue