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

Commit edfb691

Browse files
kylewuollegkalpak
authored andcommitted
fix($resource): do not swallow errors in success callback
Previously, errors thrown inside the `success` callback would be swallowed by a noop `catch()` handler. The `catch()` handler was added in order to avoid an unnecessary "Possibly Unhandled Rejection" error, in case the user provided an `error` callback (which would handle request errors). The handler was added too "eagrly" and as a result would swallow errors thrown in the `success` callback, despite the fact that those errors would _not_ be handled by the `error` callback. This commit fixes this, by adding the `catch()` handler "lazily", only when it is certain that a rejection will be handled by the `error` callback. Fixes #15624 Closes #15628
1 parent 8162362 commit edfb691

File tree

2 files changed

+80
-10
lines changed

2 files changed

+80
-10
lines changed

src/ngResource/resource.js

+10-10
Original file line numberDiff line numberDiff line change
@@ -785,18 +785,18 @@ angular.module('ngResource', ['ng']).
785785
return value;
786786
},
787787
(hasError || hasResponseErrorInterceptor) ?
788-
function(response) {
789-
if (hasError) error(response);
790-
return hasResponseErrorInterceptor ?
788+
function(response) {
789+
if (hasError && !hasResponseErrorInterceptor) {
790+
// Avoid `Possibly Unhandled Rejection` error,
791+
// but still fulfill the returned promise with a rejection
792+
promise.catch(noop);
793+
}
794+
if (hasError) error(response);
795+
return hasResponseErrorInterceptor ?
791796
responseErrorInterceptor(response) :
792797
$q.reject(response);
793-
} :
794-
undefined);
795-
if (hasError && !hasResponseErrorInterceptor) {
796-
// Avoid `Possibly Unhandled Rejection` error,
797-
// but still fulfill the returned promise with a rejection
798-
promise.catch(noop);
799-
}
798+
} :
799+
undefined);
800800

801801
if (!isInstanceCall) {
802802
// we are creating instance / collection

test/ngResource/resourceSpec.js

+70
Original file line numberDiff line numberDiff line change
@@ -1721,6 +1721,76 @@ describe('handling rejections', function() {
17211721
expect($exceptionHandler.errors[0]).toMatch(/^Possibly unhandled rejection/);
17221722
})
17231723
);
1724+
1725+
1726+
it('should not swallow exceptions in success callback when error callback is provided',
1727+
function() {
1728+
$httpBackend.expect('GET', '/CreditCard/123').respond(null);
1729+
var CreditCard = $resource('/CreditCard/:id');
1730+
var cc = CreditCard.get({id: 123},
1731+
function(res) { throw new Error('should be caught'); },
1732+
function() {});
1733+
1734+
$httpBackend.flush();
1735+
expect($exceptionHandler.errors.length).toBe(1);
1736+
expect($exceptionHandler.errors[0]).toMatch(/^Error: should be caught/);
1737+
}
1738+
);
1739+
1740+
1741+
it('should not swallow exceptions in success callback when error callback is not provided',
1742+
function() {
1743+
$httpBackend.expect('GET', '/CreditCard/123').respond(null);
1744+
var CreditCard = $resource('/CreditCard/:id');
1745+
var cc = CreditCard.get({id: 123},
1746+
function(res) { throw new Error('should be caught'); });
1747+
1748+
$httpBackend.flush();
1749+
expect($exceptionHandler.errors.length).toBe(1);
1750+
expect($exceptionHandler.errors[0]).toMatch(/^Error: should be caught/);
1751+
}
1752+
);
1753+
1754+
1755+
it('should not swallow exceptions in success callback when error callback is provided and has responseError interceptor',
1756+
function() {
1757+
$httpBackend.expect('GET', '/CreditCard/123').respond(null);
1758+
var CreditCard = $resource('/CreditCard/:id:', null, {
1759+
get: {
1760+
method: 'GET',
1761+
interceptor: {responseError: function() {}}
1762+
}
1763+
});
1764+
1765+
var cc = CreditCard.get({id: 123},
1766+
function(res) { throw new Error('should be caught'); },
1767+
function() {});
1768+
1769+
$httpBackend.flush();
1770+
expect($exceptionHandler.errors.length).toBe(1);
1771+
expect($exceptionHandler.errors[0]).toMatch(/^Error: should be caught/);
1772+
}
1773+
);
1774+
1775+
1776+
it('should not swallow exceptions in success callback when error callback is not provided and has responseError interceptor',
1777+
function() {
1778+
$httpBackend.expect('GET', '/CreditCard/123').respond(null);
1779+
var CreditCard = $resource('/CreditCard/:id', null, {
1780+
get: {
1781+
method: 'GET',
1782+
interceptor: {responseError: function() {}}
1783+
}
1784+
});
1785+
1786+
var cc = CreditCard.get({id: 123},
1787+
function(res) { throw new Error('should be caught'); });
1788+
1789+
$httpBackend.flush();
1790+
expect($exceptionHandler.errors.length).toBe(1);
1791+
expect($exceptionHandler.errors[0]).toMatch(/^Error: should be caught/);
1792+
}
1793+
);
17241794
});
17251795

17261796
describe('cancelling requests', function() {

0 commit comments

Comments
 (0)