angular-q-spread
Advanced tools
Comparing version 1.0.4 to 1.1.0
{ | ||
"name": "angular-q-spread", | ||
"version": "1.0.4", | ||
"version": "1.1.0", | ||
"homepage": "https://github.com/showpad/angular-q-spread", | ||
@@ -5,0 +5,0 @@ "description": "Add `spread` method to the promise of $q.all", |
# angular-q-spread changelog | ||
### 1.1.0 | ||
* Add `spread` on every promise | ||
### 1.0.4 | ||
@@ -4,0 +7,0 @@ * Use minified version in bower config |
@@ -10,22 +10,22 @@ (function (angular) { | ||
var originalAll = $delegate.all; | ||
var originalDefer = $delegate.defer; | ||
$delegate.all = function (promises) { | ||
var promise = originalAll(promises); | ||
$delegate.defer = function () { | ||
// Get the prototype of the promise | ||
var promiseProto = originalDefer().promise.constructor.prototype; | ||
/** | ||
* Spread method, proxies to `then` but spreads the results for the resolve callback | ||
* @param {Function} resolve | ||
* @param {Function} reject | ||
*/ | ||
promise.spread = function (resolve, reject) { | ||
// Add the spread method | ||
Object.defineProperty(promiseProto, 'spread', { | ||
value: function (resolve, reject) { | ||
function spread (data) { | ||
return resolve.apply(void 0, data); | ||
} | ||
function spread(data) { | ||
return resolve.apply(void 0, data); | ||
} | ||
return promise.then(spread, reject); | ||
}; | ||
return promise; | ||
return this.then(spread, reject); | ||
}, | ||
writable: true, | ||
enumerable: false | ||
}); | ||
return originalDefer(); | ||
}; | ||
@@ -36,2 +36,2 @@ | ||
}]); | ||
})(window.angular); | ||
})(window.angular); |
@@ -1,1 +0,1 @@ | ||
!function(n){"use strict";n.module("$q-spread",[]).config(["$provide",function(n){n.decorator("$q",["$delegate",function(n){var r=n.all;return n.all=function(n){var t=r(n);return t.spread=function(n,r){function e(r){return n.apply(void 0,r)}return t.then(e,r)},t},n}])}])}(window.angular); | ||
!function(e){"use strict";e.module("$q-spread",[]).config(["$provide",function(e){e.decorator("$q",["$delegate",function(e){var r=e.defer;return e.defer=function(){var e=r().promise.constructor.prototype;return Object.defineProperty(e,"spread",{value:function(e,r){function n(r){return e.apply(void 0,r)}return this.then(n,r)},writable:!0,enumerable:!1}),r()},e}])}])}(window.angular); |
@@ -24,3 +24,6 @@ 'use strict'; | ||
}, | ||
done | ||
function () { | ||
done(); | ||
} | ||
); | ||
@@ -27,0 +30,0 @@ |
{ | ||
"name": "angular-q-spread", | ||
"version": "1.0.4", | ||
"version": "1.1.0", | ||
"description": "Add `spread` method to the promise of $q.all", | ||
@@ -5,0 +5,0 @@ "main": "index.js", |
@@ -10,3 +10,3 @@ [![GitHub version](https://badge.fury.io/gh/showpad%2Fangular-q-spread.svg)](http://badge.fury.io/gh/showpad%2Fangular-q-spread) | ||
Add `spread` method to the promise returned by $q.all. | ||
Add `spread` method to all promises created by the $q service. | ||
@@ -16,2 +16,4 @@ `spread` can be used as a replacement for `then`. Similarly, it takes two parameters, a callback when all promises are resolved and a callback for failure. | ||
`spread` can be chained onto every promise. | ||
#Compatibility | ||
@@ -18,0 +20,0 @@ This plugin has been tested with Angular 1.2 and 1.3 |
@@ -10,22 +10,22 @@ (function (angular) { | ||
var originalAll = $delegate.all; | ||
var originalDefer = $delegate.defer; | ||
$delegate.all = function (promises) { | ||
var promise = originalAll(promises); | ||
$delegate.defer = function () { | ||
// Get the prototype of the promise | ||
var promiseProto = originalDefer().promise.constructor.prototype; | ||
/** | ||
* Spread method, proxies to `then` but spreads the results for the resolve callback | ||
* @param {Function} resolve | ||
* @param {Function} reject | ||
*/ | ||
promise.spread = function (resolve, reject) { | ||
// Add the spread method | ||
Object.defineProperty(promiseProto, 'spread', { | ||
value: function (resolve, reject) { | ||
function spread (data) { | ||
return resolve.apply(void 0, data); | ||
} | ||
function spread(data) { | ||
return resolve.apply(void 0, data); | ||
} | ||
return promise.then(spread, reject); | ||
}; | ||
return promise; | ||
return this.then(spread, reject); | ||
}, | ||
writable: true, | ||
enumerable: false | ||
}); | ||
return originalDefer(); | ||
}; | ||
@@ -36,2 +36,2 @@ | ||
}]); | ||
})(window.angular); | ||
})(window.angular); |
'use strict'; | ||
describe('$q-spread: $q.all', function() { | ||
describe('$q-spread', function() { | ||
@@ -14,52 +14,84 @@ var $q, $rootScope; | ||
describe('`then` method', function () { | ||
describe('$q.defer():', function () { | ||
it('should exist', function () { | ||
expect($q.all([]).then).toBeDefined(); | ||
var defer; | ||
beforeEach(function () { | ||
defer = new $q.defer(); | ||
window.resolveCallback = function () {}; | ||
window.rejectCallback = function () {}; | ||
}); | ||
it('should call the resolve method with 1 argument which is an array on success', function () { | ||
var defer1 = new $q.defer(), | ||
defer2 = new $q.defer(); | ||
describe('default behaviour of its promise:', function () { | ||
it('should have a then method', function () { | ||
expect(typeof defer.promise.then).toBe('function'); | ||
}); | ||
window.allSuccess = function () {}; | ||
it('should call the resolve callback when the defer is resolved', function () { | ||
spyOn(window, 'resolveCallback'); | ||
spyOn(window, 'rejectCallback'); | ||
spyOn(window, 'allSuccess').and.callThrough(); | ||
var result = 'some result'; | ||
$q | ||
.all([ | ||
defer1.promise, | ||
defer2.promise | ||
]) | ||
.then(allSuccess); | ||
defer.promise.then(resolveCallback, rejectCallback); | ||
defer.resolve(result); | ||
$rootScope.$digest(); | ||
defer1.resolve(1); | ||
defer2.resolve('b'); | ||
expect(window.resolveCallback).toHaveBeenCalledWith(result); | ||
expect(window.rejectCallback).not.toHaveBeenCalled(); | ||
}); | ||
$rootScope.$digest(); | ||
it('should call the reject callback when the defer is rejected', function () { | ||
spyOn(window, 'resolveCallback'); | ||
spyOn(window, 'rejectCallback'); | ||
expect(allSuccess).toHaveBeenCalledWith([1, 'b']); | ||
var reason = 'some reason'; | ||
defer.promise.then(resolveCallback, rejectCallback); | ||
defer.reject(reason); | ||
$rootScope.$digest(); | ||
expect(window.resolveCallback).not.toHaveBeenCalled(); | ||
expect(window.rejectCallback).toHaveBeenCalledWith(reason); | ||
}); | ||
}); | ||
it('should call the defer method with the reason of the failed defer on failure', function () { | ||
var defer1 = new $q.defer(), | ||
defer2 = new $q.defer(); | ||
describe('spread behaviour of its promise:', function () { | ||
it('should have a spread method', function () { | ||
expect(typeof defer.promise.spread).toBe('function'); | ||
}); | ||
window.allFailure = function () {}; | ||
it('should spread the results over the callback', function () { | ||
spyOn(window, 'resolveCallback'); | ||
spyOn(window, 'rejectCallback'); | ||
spyOn(window, 'allFailure').and.callThrough(); | ||
var result = ['result 1', 'result 2']; | ||
$q | ||
.all([ | ||
defer1.promise, | ||
defer2.promise | ||
]) | ||
.then(null, allFailure); | ||
defer.promise.spread(resolveCallback, rejectCallback); | ||
defer.resolve(result); | ||
$rootScope.$digest(); | ||
defer1.resolve(1); | ||
defer2.reject('b'); | ||
expect(window.resolveCallback).toHaveBeenCalledWith(result[0], result[1]); | ||
expect(window.rejectCallback).not.toHaveBeenCalled(); | ||
}); | ||
$rootScope.$digest(); | ||
it('should reject the same way as then', function () { | ||
spyOn(window, 'resolveCallback'); | ||
spyOn(window, 'rejectCallback'); | ||
expect(allFailure).toHaveBeenCalledWith('b'); | ||
var reason = ['reason 1', 'reason 2']; | ||
defer.promise.spread(resolveCallback, rejectCallback); | ||
defer.reject(reason); | ||
$rootScope.$digest(); | ||
expect(window.resolveCallback).not.toHaveBeenCalled(); | ||
// regular call, not spread | ||
expect(window.rejectCallback).toHaveBeenCalledWith(reason); | ||
}); | ||
it('should be chainable', function () { | ||
expect(typeof defer.promise.spread().then).toBe('function') | ||
}); | ||
}); | ||
@@ -69,80 +101,197 @@ | ||
describe('`spread` method', function () { | ||
describe('$q.when():', function () { | ||
it('should exist', function () { | ||
expect($q.all([]).spread).toBeDefined(); | ||
beforeEach(function () { | ||
window.resolveCallback = function () {}; | ||
window.rejectCallback = function () {}; | ||
}); | ||
it('should call the resolve method with list of arguments which is an array on success', function () { | ||
var defer1 = new $q.defer(), | ||
defer2 = new $q.defer(); | ||
describe('default behaviour:', function () { | ||
it('should have a then method', function () { | ||
expect(typeof $q.when().then).toBe('function'); | ||
}); | ||
window.allSuccess = function (result1, result2) {}; | ||
it('should resolve the promise with the specified value', function () { | ||
spyOn(window, 'resolveCallback'); | ||
spyOn(window, 'rejectCallback'); | ||
spyOn(window, 'allSuccess').and.callThrough(); | ||
var result = 'some result'; | ||
$q | ||
.all([ | ||
defer1.promise, | ||
defer2.promise | ||
]) | ||
.spread(allSuccess); | ||
$q.when(result).then(resolveCallback, rejectCallback); | ||
$rootScope.$digest(); | ||
defer1.resolve(1); | ||
defer2.resolve('b'); | ||
expect(window.resolveCallback).toHaveBeenCalledWith(result); | ||
expect(window.rejectCallback).not.toHaveBeenCalled(); | ||
}); | ||
}); | ||
$rootScope.$digest(); | ||
describe('spread behaviour:', function () { | ||
it('should have a spread method', function () { | ||
expect(typeof $q.when().spread).toBe('function'); | ||
}); | ||
expect(allSuccess).toHaveBeenCalledWith(1, 'b'); | ||
it('should spread the results over the callback', function () { | ||
spyOn(window, 'resolveCallback'); | ||
spyOn(window, 'rejectCallback'); | ||
var result = ['result 1', 'result 2']; | ||
$q.when(result).spread(resolveCallback, rejectCallback); | ||
$rootScope.$digest(); | ||
expect(window.resolveCallback).toHaveBeenCalledWith(result[0], result[1]); | ||
expect(window.rejectCallback).not.toHaveBeenCalled(); | ||
}); | ||
it('should be chainable', function () { | ||
expect(typeof $q.when().spread().then).toBe('function'); | ||
}); | ||
}); | ||
}); | ||
it('should call the defer method with the reason of the failed defer on failure', function () { | ||
var defer1 = new $q.defer(), | ||
defer2 = new $q.defer(); | ||
describe('$q.all():', function () { | ||
window.allFailure = function () {}; | ||
beforeEach(function () { | ||
window.resolveCallback = function () {}; | ||
window.rejectCallback = function () {}; | ||
}); | ||
spyOn(window, 'allFailure').and.callThrough(); | ||
describe('default behaviour:', function () { | ||
it('should have a then method', function () { | ||
expect(typeof $q.all([]).then).toBe('function'); | ||
}); | ||
$q | ||
.all([ | ||
defer1.promise, | ||
defer2.promise | ||
]) | ||
.spread(null, allFailure); | ||
it('should resolve the promise with an array with the results of all its promises', function () { | ||
spyOn(window, 'resolveCallback'); | ||
spyOn(window, 'rejectCallback'); | ||
defer1.resolve(1); | ||
defer2.reject('b'); | ||
var result1 = 'result 1'; | ||
var result2 = 'result 2'; | ||
$rootScope.$digest(); | ||
$q | ||
.all([$q.when(result1), $q.when(result2)]) | ||
.then(resolveCallback, rejectCallback); | ||
expect(allFailure).toHaveBeenCalledWith('b'); | ||
$rootScope.$digest(); | ||
expect(window.resolveCallback).toHaveBeenCalledWith([result1, result2]); | ||
expect(window.rejectCallback).not.toHaveBeenCalled(); | ||
}); | ||
it('should reject the promise when one of its promises fails', function () { | ||
spyOn(window, 'resolveCallback'); | ||
spyOn(window, 'rejectCallback'); | ||
var result1 = 'result 1'; | ||
var reason2 = 'reason 2'; | ||
$q | ||
.all([$q.when(result1), $q.reject(reason2)]) | ||
.then(resolveCallback, rejectCallback); | ||
$rootScope.$digest(); | ||
expect(window.resolveCallback).not.toHaveBeenCalled(); | ||
expect(window.rejectCallback).toHaveBeenCalledWith(reason2); | ||
}); | ||
}); | ||
it('should return a value which can be read by the next promise in the chain', function () { | ||
var defer1 = new $q.defer(), | ||
defer2 = new $q.defer(); | ||
describe('spread behaviour:', function () { | ||
it('should have a spread method', function () { | ||
expect(typeof $q.all([]).spread).toBe('function'); | ||
}); | ||
window.spreadResult = function () {}; | ||
it('should spread the results over the callback', function () { | ||
spyOn(window, 'resolveCallback'); | ||
spyOn(window, 'rejectCallback'); | ||
spyOn(window, 'spreadResult').and.callThrough(); | ||
var result1 = 'result 1'; | ||
var result2 = 'result 2'; | ||
$q | ||
.all([ | ||
defer1.promise, | ||
defer2.promise | ||
]) | ||
.spread(function(result1, result2) { | ||
return result1 + result2; | ||
}).then(spreadResult); | ||
$q | ||
.all([ $q.when(result1), $q.when(result2) ]) | ||
.spread(resolveCallback, rejectCallback); | ||
$rootScope.$digest(); | ||
defer1.resolve(1); | ||
defer2.resolve(2); | ||
expect(window.resolveCallback).toHaveBeenCalledWith(result1, result2); | ||
expect(window.rejectCallback).not.toHaveBeenCalled(); | ||
}); | ||
it('should call reject callback with the plain reason when on of its promises is rejected', function () { | ||
spyOn(window, 'resolveCallback'); | ||
spyOn(window, 'rejectCallback'); | ||
var result1 = 'result 1'; | ||
var reason2 = 'reason 2'; | ||
$q | ||
.all([ $q.when(result1), $q.reject(reason2) ]) | ||
.spread(resolveCallback, rejectCallback); | ||
$rootScope.$digest(); | ||
expect(window.resolveCallback).not.toHaveBeenCalled(); | ||
expect(window.rejectCallback).toHaveBeenCalledWith(reason2); | ||
}); | ||
it('should be chainable', function () { | ||
expect(typeof $q.all([]).spread().then).toBe('function'); | ||
}); | ||
}); | ||
}); | ||
describe('$q.then():', function () { | ||
beforeEach(function () { | ||
window.resolveCallback1 = function (data1, data2) { | ||
return data1 + ' ' + data2; | ||
}; | ||
window.rejectCallback1 = function () {}; | ||
window.resolveCallback2 = function (data1, data2) { | ||
return data1 + '-' + data2; | ||
}; | ||
window.rejectCallback2 = function () {}; | ||
window.finalCallback = function () {}; | ||
}); | ||
it('should implement spread behaviour', function () { | ||
spyOn(window, 'resolveCallback1').and.callThrough(); | ||
spyOn(window, 'rejectCallback1').and.callThrough(); | ||
spyOn(window, 'resolveCallback2').and.callThrough(); | ||
spyOn(window, 'rejectCallback2').and.callThrough(); | ||
spyOn(window, 'finalCallback').and.callThrough(); | ||
var result1 = 'result 1'; | ||
var result2 = 'result 2'; | ||
var result3 = 'result 3'; | ||
$q.when(result1) | ||
.then(function (firstResult) { | ||
return $q.all([ $q.when(firstResult), $q.when(result2) ]); | ||
}) | ||
.spread(window.resolveCallback1, window.rejectCallback1) | ||
.then(function (secondResult) { | ||
return [secondResult, result3]; | ||
}) | ||
.spread(window.resolveCallback2, window.rejectCallback2) | ||
.then(finalCallback); | ||
$rootScope.$digest(); | ||
expect(spreadResult).toHaveBeenCalledWith(3); | ||
expect(window.rejectCallback1).not.toHaveBeenCalled(); | ||
expect(window.rejectCallback2).not.toHaveBeenCalled(); | ||
expect(window.resolveCallback1).toHaveBeenCalledWith(result1, result2); | ||
expect(window.resolveCallback2).toHaveBeenCalledWith(result1 + ' ' + result2, result3); | ||
expect(window.finalCallback).toHaveBeenCalledWith(result1 + ' ' + result2 + '-' + result3); | ||
}); | ||
}); | ||
}); |
22044
391
60