-
Notifications
You must be signed in to change notification settings - Fork 27.4k
allow json callback customisation #14795
Changes from all commits
5253d65
c1a335d
bdb210d
d7dfeab
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,83 @@ | ||
'use strict'; | ||
|
||
/** | ||
* @ngdoc service | ||
* @name $jsonpCallbacks | ||
* @requires $window | ||
* @description | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I'm not sure we are consistent with all services, but could add a There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Done |
||
* This service handles the lifecycle of callbacks to handle JSONP requests. | ||
* Override this service if you wish to customise where the callbacks are stored and | ||
* how they vary compared to the requested url. | ||
*/ | ||
var $jsonpCallbacksProvider = function() { | ||
this.$get = ['$window', function($window) { | ||
var counter = 0; | ||
$window.angular.callbacks = {}; | ||
var callbackMap = {}; | ||
|
||
function createCallback(callbackId) { | ||
var callback = function(data) { | ||
callback.data = data; | ||
callback.called = true; | ||
}; | ||
callback.id = callbackId; | ||
return callback; | ||
} | ||
|
||
return { | ||
/** | ||
* @ngdoc method | ||
* @name $jsonpCallbacks#createCallback | ||
* @param {string} url the url of the JSONP request | ||
* @returns {string} the callback path to send to the server as part of the JSONP request | ||
* @description | ||
* {@link $httpBackend} calls this method to create a callback and get hold of the path to the callback | ||
* to pass to the server, which will be used to call the callback with its payload in the JSONP response. | ||
*/ | ||
createCallback: function(url) { | ||
var callbackId = '_' + (counter++).toString(36); | ||
var callbackPath = 'angular.callbacks.' + callbackId; | ||
var callback = createCallback(callbackId); | ||
callbackMap[callbackPath] = $window.angular.callbacks[callbackId] = callback; | ||
return callbackPath; | ||
}, | ||
/** | ||
* @ngdoc method | ||
* @name $jsonpCallbacks#wasCalled | ||
* @param {string} callbackPath the path to the callback that was sent in the JSONP request | ||
* @returns {boolean} whether the callback has been called, as a result of the JSONP response | ||
* @description | ||
* {@link $httpBackend} calls this method to find out whether the JSONP response actually called the | ||
* callback that was passed in the request. | ||
*/ | ||
wasCalled: function(callbackPath) { | ||
return callbackMap[callbackPath].called; | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Since we are deleting the entries, do we need to safeguard against the There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. According to the way that I have written it in |
||
}, | ||
/** | ||
* @ngdoc method | ||
* @name $jsonpCallbacks#getResponse | ||
* @param {string} callbackPath the path to the callback that was sent in the JSONP request | ||
* @returns {*} the data received from the response via the registered callback | ||
* @description | ||
* {@link $httpBackend} calls this method to get hold of the data that was provided to the callback | ||
* in the JSONP response. | ||
*/ | ||
getResponse: function(callbackPath) { | ||
return callbackMap[callbackPath].data; | ||
}, | ||
/** | ||
* @ngdoc method | ||
* @name $jsonpCallbacks#removeCallback | ||
* @param {string} callbackPath the path to the callback that was sent in the JSONP request | ||
* @description | ||
* {@link $httpBackend} calls this method to remove the callback after the JSONP request has | ||
* completed or timed-out. | ||
*/ | ||
removeCallback: function(callbackPath) { | ||
var callback = callbackMap[callbackPath]; | ||
delete $window.angular.callbacks[callback.id]; | ||
delete callbackMap[callbackPath]; | ||
} | ||
}; | ||
}]; | ||
}; |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,73 @@ | ||
'use strict'; | ||
|
||
describe('$jsonpCallbacks', function() { | ||
|
||
beforeEach(module(function($provide) { | ||
// mock out the $window object | ||
$provide.value('$window', { angular: {} }); | ||
})); | ||
|
||
describe('createCallback(url)', function() { | ||
|
||
it('should return a new unique path to a callback function on each call', inject(function($jsonpCallbacks) { | ||
var path = $jsonpCallbacks.createCallback('http://some.dummy.com/jsonp/request'); | ||
expect(path).toEqual('angular.callbacks._0'); | ||
|
||
path = $jsonpCallbacks.createCallback('http://some.dummy.com/jsonp/request'); | ||
expect(path).toEqual('angular.callbacks._1'); | ||
|
||
path = $jsonpCallbacks.createCallback('http://some.dummy.com/jsonp/request'); | ||
expect(path).toEqual('angular.callbacks._2'); | ||
|
||
path = $jsonpCallbacks.createCallback('http://some.dummy.com/jsonp/request'); | ||
expect(path).toEqual('angular.callbacks._3'); | ||
})); | ||
|
||
it('should add a callback method to the $window.angular.callbacks collection on each call', inject(function($window, $jsonpCallbacks) { | ||
$jsonpCallbacks.createCallback('http://some.dummy.com/jsonp/request'); | ||
expect($window.angular.callbacks._0).toEqual(jasmine.any(Function)); | ||
|
||
$jsonpCallbacks.createCallback('http://some.dummy.com/jsonp/request'); | ||
expect($window.angular.callbacks._1).toEqual(jasmine.any(Function)); | ||
|
||
$jsonpCallbacks.createCallback('http://some.dummy.com/jsonp/request'); | ||
expect($window.angular.callbacks._2).toEqual(jasmine.any(Function)); | ||
|
||
$jsonpCallbacks.createCallback('http://some.dummy.com/jsonp/request'); | ||
expect($window.angular.callbacks._3).toEqual(jasmine.any(Function)); | ||
})); | ||
}); | ||
|
||
|
||
describe('wasCalled(callbackPath)', function() { | ||
|
||
it('should return true once the callback has been called', inject(function($window, $jsonpCallbacks) { | ||
var path = $jsonpCallbacks.createCallback('http://some.dummy.com/jsonp/request'); | ||
expect($jsonpCallbacks.wasCalled(path)).toBeFalsy(); | ||
var response = {}; | ||
$window.angular.callbacks._0(response); | ||
expect($jsonpCallbacks.wasCalled(path)).toBeTruthy(); | ||
})); | ||
}); | ||
|
||
|
||
describe('getResponse(callbackPath)', function() { | ||
|
||
it('should retrieve the data from when the callback was called', inject(function($window, $jsonpCallbacks) { | ||
var path = $jsonpCallbacks.createCallback('http://some.dummy.com/jsonp/request'); | ||
var response = {}; | ||
$window.angular.callbacks._0(response); | ||
var result = $jsonpCallbacks.getResponse(path); | ||
expect(result).toBe(response); | ||
})); | ||
}); | ||
|
||
describe('removeCallback(calbackPath)', function() { | ||
|
||
it('should remove the callback', inject(function($window, $jsonpCallbacks) { | ||
var path = $jsonpCallbacks.createCallback('http://some.dummy.com/jsonp/request'); | ||
$jsonpCallbacks.removeCallback(path); | ||
expect($window.angular.callbacks._0).toBeUndefined(); | ||
})); | ||
}); | ||
}); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Minor: I would add a note that
status
is set injsonpReq()
and it can be either-1
,404
or200
.The first time I saw this, I thought: "What if it is in the (200, 300) range?"