From 3ae3ccf3dab95793c868d626a4560aacf3cae796 Mon Sep 17 00:00:00 2001 From: Vojta Jina Date: Thu, 18 Aug 2011 23:43:25 +0200 Subject: fix($browser.xhr): fix IE6, IE7 bug - sync xhr when serving from cache IE6, IE7 is sync when serving content from cache. We want consistent api, so we have to use setTimeout to make it async. --- src/service/browser.js | 27 ++++++++++++++++++++------- test/service/browserSpecs.js | 29 +++++++++++++++++++++++++++++ 2 files changed, 49 insertions(+), 7 deletions(-) diff --git a/src/service/browser.js b/src/service/browser.js index 49bfe99e..b38c9211 100644 --- a/src/service/browser.js +++ b/src/service/browser.js @@ -73,6 +73,11 @@ function Browser(window, document, body, XHR, $log, $sniffer) { } } + // normalize IE bug (http://bugs.jquery.com/ticket/1450) + function fixStatus(status) { + return status == 1223 ? 204 : status; + } + /** * @ngdoc method * @name angular.module.ng.$browser#xhr @@ -120,14 +125,22 @@ function Browser(window, document, body, XHR, $log, $sniffer) { forEach(headers, function(value, key) { if (value) xhr.setRequestHeader(key, value); }); - xhr.onreadystatechange = function() { - if (xhr.readyState == 4) { - // normalize IE bug (http://bugs.jquery.com/ticket/1450) - var status = xhr.status == 1223 ? 204 : xhr.status; - completeOutstandingRequest(callback, status, xhr.responseText); - } - }; + xhr.send(post || ''); + + // IE6, IE7 bug - does sync when serving from cache + if (xhr.readyState == 4) { + setTimeout(function() { + completeOutstandingRequest(callback, fixStatus(xhr.status), xhr.responseText); + }, 0); + } else { + xhr.onreadystatechange = function() { + if (xhr.readyState == 4) { + completeOutstandingRequest(callback, fixStatus(xhr.status), xhr.responseText); + } + }; + } + return xhr; } }; diff --git a/test/service/browserSpecs.js b/test/service/browserSpecs.js index a3ec6486..05c1dec0 100644 --- a/test/service/browserSpecs.js +++ b/test/service/browserSpecs.js @@ -227,6 +227,35 @@ describe('browser', function() { it('should return raw xhr object', function() { expect(browser.xhr('GET', '/url', null, noop)).toBe(xhr); }); + + it('should be async even if xhr.send() is sync', function() { + // IE6, IE7 is sync when serving from cache + var xhr; + function FakeXhr() { + xhr = this; + this.open = this.setRequestHeader = noop; + this.send = function() { + this.status = 200; + this.responseText = 'response'; + this.readyState = 4; + }; + } + + var callback = jasmine.createSpy('done').andCallFake(function(status, response) { + expect(status).toBe(200); + expect(response).toBe('response'); + }); + + browser = new Browser(fakeWindow, jqLite(window.document), null, FakeXhr, null); + browser.xhr('GET', '/url', null, callback); + expect(callback).not.toHaveBeenCalled(); + + fakeWindow.setTimeout.flush(); + expect(callback).toHaveBeenCalledOnce(); + + (xhr.onreadystatechange || noop)(); + expect(callback).toHaveBeenCalledOnce(); + }); }); describe('defer', function() { -- cgit v1.2.3