mirror of
https://github.com/Hopiu/angular.js.git
synced 2026-05-28 07:23:59 +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
718ebf1fcf
commit
05e2c3196c
2 changed files with 93 additions and 23 deletions
|
|
@ -100,12 +100,19 @@ function Browser(window, document, body, XHR, $log) {
|
||||||
outstandingRequestCount ++;
|
outstandingRequestCount ++;
|
||||||
if (lowercase(method) == 'json') {
|
if (lowercase(method) == 'json') {
|
||||||
var callbackId = ("angular_" + Math.random() + '_' + (idCounter++)).replace(/\d\./, '');
|
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];
|
delete window[callbackId];
|
||||||
body[0].removeChild(script);
|
body[0].removeChild(script);
|
||||||
completeOutstandingRequest(callback, 200, data);
|
});
|
||||||
};
|
|
||||||
} else {
|
} else {
|
||||||
var xhr = new XHR();
|
var xhr = new XHR();
|
||||||
xhr.open(method, url, true);
|
xhr.open(method, url, true);
|
||||||
|
|
@ -452,7 +459,7 @@ function Browser(window, document, body, XHR, $log) {
|
||||||
* @description
|
* @description
|
||||||
* Adds a script tag to the head.
|
* 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.:
|
// 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
|
// - fetches local scripts via XHR and evals them
|
||||||
// - adds and immediately removes script elements from the document
|
// - 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.type = 'text/javascript';
|
||||||
script.src = url;
|
script.src = url;
|
||||||
if (domId) script.id = domId;
|
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);
|
body[0].appendChild(script);
|
||||||
|
|
||||||
return script;
|
return script;
|
||||||
|
|
|
||||||
|
|
@ -87,27 +87,81 @@ describe('browser', function(){
|
||||||
|
|
||||||
describe('xhr', function(){
|
describe('xhr', function(){
|
||||||
describe('JSON', function(){
|
describe('JSON', function(){
|
||||||
it('should add script tag for request', function() {
|
var log;
|
||||||
var callback = jasmine.createSpy('callback');
|
|
||||||
var log = "";
|
function callback(code, data) {
|
||||||
browser.xhr('JSON', 'http://example.org/path?cb=JSON_CALLBACK', null, function(code, data){
|
log += code + ':' + data + ';';
|
||||||
log += code + ':' + data + ';';
|
}
|
||||||
});
|
|
||||||
browser.notifyWhenNoOutstandingRequests(callback);
|
beforeEach(function() {
|
||||||
expect(callback).not.toHaveBeenCalled();
|
log = "";
|
||||||
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();
|
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
||||||
|
// 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() {
|
it('should normalize IE\'s 1223 status code into 204', function() {
|
||||||
var callback = jasmine.createSpy('XHR');
|
var callback = jasmine.createSpy('XHR');
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue