Skip to content
This repository was archived by the owner on Apr 12, 2024. It is now read-only.

Commit b5594a7

Browse files
kseamonIgorMinar
authored andcommitted
feat($xhr): add custom error callback to $xhr, $xhr.cache, $xhr.bulk, $resource
Closes #408
1 parent f39420e commit b5594a7

10 files changed

+291
-124
lines changed

src/Resource.js

+42-27
Original file line numberDiff line numberDiff line change
@@ -67,53 +67,57 @@ ResourceFactory.prototype = {
6767

6868
forEach(actions, function(action, name){
6969
var isPostOrPut = action.method == 'POST' || action.method == 'PUT';
70-
Resource[name] = function (a1, a2, a3) {
70+
Resource[name] = function (a1, a2, a3, a4) {
7171
var params = {};
7272
var data;
73-
var callback = noop;
73+
var success = noop;
74+
var error = null;
7475
switch(arguments.length) {
75-
case 3: callback = a3;
76+
case 4:
77+
error = a4;
78+
success = a3;
79+
case 3:
7680
case 2:
7781
if (isFunction(a2)) {
78-
callback = a2;
82+
success = a2;
83+
error = a3;
7984
//fallthrough
8085
} else {
8186
params = a1;
8287
data = a2;
88+
success = a3;
8389
break;
8490
}
8591
case 1:
86-
if (isFunction(a1)) callback = a1;
92+
if (isFunction(a1)) success = a1;
8793
else if (isPostOrPut) data = a1;
8894
else params = a1;
8995
break;
9096
case 0: break;
9197
default:
92-
throw "Expected between 0-3 arguments [params, data, callback], got " + arguments.length + " arguments.";
98+
throw "Expected between 0-4 arguments [params, data, success, error], got " +
99+
arguments.length + " arguments.";
93100
}
94101

95102
var value = this instanceof Resource ? this : (action.isArray ? [] : new Resource(data));
96103
self.xhr(
97104
action.method,
98105
route.url(extend({}, action.params || {}, extractParams(data), params)),
99106
data,
100-
function(status, response, clear) {
101-
if (200 <= status && status < 300) {
102-
if (response) {
103-
if (action.isArray) {
104-
value.length = 0;
105-
forEach(response, function(item){
106-
value.push(new Resource(item));
107-
});
108-
} else {
109-
copy(response, value);
110-
}
107+
function(status, response) {
108+
if (response) {
109+
if (action.isArray) {
110+
value.length = 0;
111+
forEach(response, function(item) {
112+
value.push(new Resource(item));
113+
});
114+
} else {
115+
copy(response, value);
111116
}
112-
(callback||noop)(value);
113-
} else {
114-
throw {status: status, response:response, message: status + ": " + response};
115117
}
118+
(success||noop)(value);
116119
},
120+
error || action.verifyCache,
117121
action.verifyCache);
118122
return value;
119123
};
@@ -122,18 +126,29 @@ ResourceFactory.prototype = {
122126
return self.route(url, extend({}, paramDefaults, additionalParamDefaults), actions);
123127
};
124128

125-
Resource.prototype['$' + name] = function(a1, a2){
126-
var params = extractParams(this);
127-
var callback = noop;
129+
Resource.prototype['$' + name] = function(a1, a2, a3) {
130+
var params = extractParams(this),
131+
success = noop,
132+
error;
133+
128134
switch(arguments.length) {
129-
case 2: params = a1; callback = a2;
130-
case 1: if (typeof a1 == $function) callback = a1; else params = a1;
135+
case 3: params = a1; success = a2; error = a3; break;
136+
case 2:
137+
case 1:
138+
if (isFunction(a1)) {
139+
success = a1;
140+
error = a2;
141+
} else {
142+
params = a1;
143+
success = a2 || noop;
144+
}
131145
case 0: break;
132146
default:
133-
throw "Expected between 1-2 arguments [params, callback], got " + arguments.length + " arguments.";
147+
throw "Expected between 1-3 arguments [params, success, error], got " +
148+
arguments.length + " arguments.";
134149
}
135150
var data = isPostOrPut ? this : undefined;
136-
Resource[name].call(this, params, data, callback);
151+
Resource[name].call(this, params, data, success, error);
137152
};
138153
});
139154
return Resource;

src/service/resource.js

+5-5
Original file line numberDiff line numberDiff line change
@@ -82,9 +82,9 @@
8282
* The action methods on the class object or instance object can be invoked with the following
8383
* parameters:
8484
*
85-
* - HTTP GET "class" actions: `Resource.action([parameters], [callback])`
86-
* - non-GET "class" actions: `Resource.action(postData, [parameters], [callback])`
87-
* - non-GET instance actions: `instance.$action([parameters], [callback])`
85+
* - HTTP GET "class" actions: `Resource.action([parameters], [success], [error])`
86+
* - non-GET "class" actions: `Resource.action(postData, [parameters], [success], [error])`
87+
* - non-GET instance actions: `instance.$action([parameters], [success], [error])`
8888
*
8989
*
9090
* @example
@@ -142,8 +142,8 @@
142142
});
143143
</pre>
144144
*
145-
* It's worth noting that the callback for `get`, `query` and other method gets passed in the
146-
* response that came from the server, so one could rewrite the above example as:
145+
* It's worth noting that the success callback for `get`, `query` and other method gets passed
146+
* in the response that came from the server, so one could rewrite the above example as:
147147
*
148148
<pre>
149149
var User = $resource('/user/:userId', {userId:'@id'});

src/service/xhr.bulk.js

+42-18
Original file line numberDiff line numberDiff line change
@@ -15,9 +15,10 @@
1515
angularServiceInject('$xhr.bulk', function($xhr, $error, $log){
1616
var requests = [],
1717
scope = this;
18-
function bulkXHR(method, url, post, callback) {
18+
function bulkXHR(method, url, post, success, error) {
1919
if (isFunction(post)) {
20-
callback = post;
20+
error = success;
21+
success = post;
2122
post = null;
2223
}
2324
var currentQueue;
@@ -28,32 +29,55 @@ angularServiceInject('$xhr.bulk', function($xhr, $error, $log){
2829
});
2930
if (currentQueue) {
3031
if (!currentQueue.requests) currentQueue.requests = [];
31-
currentQueue.requests.push({method: method, url: url, data:post, callback:callback});
32+
var request = {
33+
method: method,
34+
url: url,
35+
data: post,
36+
success: success};
37+
if (error) request.error = error;
38+
currentQueue.requests.push(request);
3239
} else {
33-
$xhr(method, url, post, callback);
40+
$xhr(method, url, post, success, error);
3441
}
3542
}
3643
bulkXHR.urls = {};
37-
bulkXHR.flush = function(callback){
38-
forEach(bulkXHR.urls, function(queue, url){
44+
bulkXHR.flush = function(success, error) {
45+
forEach(bulkXHR.urls, function(queue, url) {
3946
var currentRequests = queue.requests;
4047
if (currentRequests && currentRequests.length) {
4148
queue.requests = [];
4249
queue.callbacks = [];
43-
$xhr('POST', url, {requests:currentRequests}, function(code, response){
44-
forEach(response, function(response, i){
45-
try {
46-
if (response.status == 200) {
47-
(currentRequests[i].callback || noop)(response.status, response.response);
48-
} else {
49-
$error(currentRequests[i], response);
50+
$xhr('POST', url, {requests: currentRequests},
51+
function(code, response) {
52+
forEach(response, function(response, i) {
53+
try {
54+
if (response.status == 200) {
55+
(currentRequests[i].success || noop)(response.status, response.response);
56+
} else if (isFunction(currentRequests[i].error)) {
57+
currentRequests[i].error(response.status, response.response);
58+
} else {
59+
$error(currentRequests[i], response);
60+
}
61+
} catch(e) {
62+
$log.error(e);
5063
}
51-
} catch(e) {
52-
$log.error(e);
53-
}
64+
});
65+
(success || noop)();
66+
},
67+
function(code, response) {
68+
forEach(currentRequests, function(request, i) {
69+
try {
70+
if (isFunction(request.error)) {
71+
request.error(code, response);
72+
} else {
73+
$error(request, response);
74+
}
75+
} catch(e) {
76+
$log.error(e);
77+
}
78+
});
79+
(error || noop)();
5480
});
55-
(callback || noop)();
56-
});
5781
scope.$eval();
5882
}
5983
});

src/service/xhr.cache.js

+65-25
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,11 @@
55
* @ngdoc service
66
* @name angular.service.$xhr.cache
77
* @function
8-
* @requires $xhr
8+
*
9+
* @requires $xhr.bulk
10+
* @requires $defer
11+
* @requires $xhr.error
12+
* @requires $log
913
*
1014
* @description
1115
* Acts just like the {@link angular.service.$xhr $xhr} service but caches responses for `GET`
@@ -18,58 +22,94 @@
1822
* @param {string} method HTTP method.
1923
* @param {string} url Destination URL.
2024
* @param {(string|Object)=} post Request body.
21-
* @param {function(number, (string|Object))} callback Response callback.
25+
* @param {function(number, (string|Object))} success Response success callback.
26+
* @param {function(number, (string|Object))=} error Response error callback.
2227
* @param {boolean=} [verifyCache=false] If `true` then a result is immediately returned from cache
2328
* (if present) while a request is sent to the server for a fresh response that will update the
24-
* cached entry. The `callback` function will be called when the response is received.
25-
* @param {boolean=} [sync=false] in case of cache hit execute `callback` synchronously.
29+
* cached entry. The `success` function will be called when the response is received.
30+
* @param {boolean=} [sync=false] in case of cache hit execute `success` synchronously.
2631
*/
27-
angularServiceInject('$xhr.cache', function($xhr, $defer, $log){
32+
angularServiceInject('$xhr.cache', function($xhr, $defer, $error, $log) {
2833
var inflight = {}, self = this;
29-
function cache(method, url, post, callback, verifyCache, sync){
34+
function cache(method, url, post, success, error, verifyCache, sync) {
3035
if (isFunction(post)) {
31-
callback = post;
36+
if (!isFunction(success)) {
37+
verifyCache = success;
38+
sync = error;
39+
error = null;
40+
} else {
41+
sync = verifyCache;
42+
verifyCache = error;
43+
error = success;
44+
}
45+
success = post;
3246
post = null;
47+
} else if (!isFunction(error)) {
48+
sync = verifyCache;
49+
verifyCache = error;
50+
error = null;
3351
}
52+
3453
if (method == 'GET') {
3554
var data, dataCached;
3655
if (dataCached = cache.data[url]) {
3756

3857
if (sync) {
39-
callback(200, copy(dataCached.value));
58+
success(200, copy(dataCached.value));
4059
} else {
41-
$defer(function() { callback(200, copy(dataCached.value)); });
60+
$defer(function() { success(200, copy(dataCached.value)); });
4261
}
4362

4463
if (!verifyCache)
4564
return;
4665
}
4766

4867
if (data = inflight[url]) {
49-
data.callbacks.push(callback);
68+
data.successes.push(success);
69+
data.errors.push(error);
5070
} else {
51-
inflight[url] = {callbacks: [callback]};
52-
cache.delegate(method, url, post, function(status, response){
53-
if (status == 200)
54-
cache.data[url] = { value: response };
55-
var callbacks = inflight[url].callbacks;
56-
delete inflight[url];
57-
forEach(callbacks, function(callback){
58-
try {
59-
(callback||noop)(status, copy(response));
60-
} catch(e) {
61-
$log.error(e);
62-
}
71+
inflight[url] = {successes: [success], errors: [error]};
72+
cache.delegate(method, url, post,
73+
function(status, response) {
74+
if (status == 200)
75+
cache.data[url] = {value: response};
76+
var successes = inflight[url].successes;
77+
delete inflight[url];
78+
forEach(successes, function(success) {
79+
try {
80+
(success||noop)(status, copy(response));
81+
} catch(e) {
82+
$log.error(e);
83+
}
84+
});
85+
},
86+
function(status, response) {
87+
var errors = inflight[url].errors,
88+
successes = inflight[url].successes;
89+
delete inflight[url];
90+
91+
forEach(errors, function(error, i) {
92+
try {
93+
if (isFunction(error)) {
94+
error(status, copy(response));
95+
} else {
96+
$error(
97+
{method: method, url: url, data: post, success: successes[i]},
98+
{status: status, body: response});
99+
}
100+
} catch(e) {
101+
$log.error(e);
102+
}
103+
});
63104
});
64-
});
65105
}
66106

67107
} else {
68108
cache.data = {};
69-
cache.delegate(method, url, post, callback);
109+
cache.delegate(method, url, post, success, error);
70110
}
71111
}
72112
cache.data = {};
73113
cache.delegate = $xhr;
74114
return cache;
75-
}, ['$xhr.bulk', '$defer', '$log']);
115+
}, ['$xhr.bulk', '$defer', '$xhr.error', '$log']);

0 commit comments

Comments
 (0)