Add some promise helpers to lodash

This commit is contained in:
Joe Fiorini 2015-05-15 16:46:34 -04:00
parent 862cc40de0
commit ae5594a853
3 changed files with 192 additions and 0 deletions

View File

@ -0,0 +1,115 @@
function lodashAsPromised($q) {
var lodash = _.runInContext();
var _aw = {};
var toExtend =
[ 'map',
'filter',
'reduce',
'pluck',
'compact',
'xor',
'groupBy',
'thru'
];
function log(label, obj) {
/* jshint ignore:start */
console.log(label, obj);
/* jshint ignore:end */
return obj;
}
function _reject(value, reason) {
return $q.reject(reason);
}
function _promise(value) {
return $q.when(value);
}
function _then(promise, fn) {
return promise.then(fn);
}
function _catch(promise, fn) {
return promise.catch(fn);
}
function _finally(promise, fn) {
return promise.finally(fn);
}
function thenAll(arr, then, deep) {
var doAll = function (arr) {
var promise = $q.all(arr).then(function (resolvedArr) {
if (deep) {
return lodash(resolvedArr)
.thenMap(function (elem) {
if (_.isArray(elem)) {
return thenAll(elem, null, true);
} else {
return elem;
}
})
.thenAll()
.value();
} else {
return resolvedArr;
}
});
return then ? promise.then(then) : promise;
};
if (arr.then) {
return arr.then(doAll);
} else {
return doAll(arr);
}
}
function thenFlatten(array, isShallow, callback, thisArg) {
return thenAll(array, _.partialRight(_.flatten, isShallow, callback, thisArg), true);
}
function wrapCallback(method, callback, thisArg, collection) {
return method(collection, function(value, index, collection) {
if (_.isFunction(value.then)) {
return value.then(_.partialRight(callback, index, collection));
} else {
return callback(value, index, collection);
}
}, thisArg);
}
function promiseWrapper(method, collection, callback, thisArg) {
if (_.isFunction(collection.then)) {
return collection.then(
_.partial(wrapCallback, method, callback, thisArg));
} else {
return $q.all(collection)
.then(function(unwrappedResults) {
return method(unwrappedResults, callback, thisArg);
});
}
}
toExtend.forEach(function(fnName) {
var wrappedName = 'then' + _.capitalize(fnName);
_aw[wrappedName] = _.partial(promiseWrapper, _[fnName]);
});
_aw.promise = _promise;
_aw.reject = _reject;
_aw.then = _then;
_aw.catch = _catch;
_aw.finally = _finally;
_aw.thenAll = thenAll;
_aw.thenFlatten = thenFlatten;
_aw.log = log;
lodash.mixin(_aw);
return lodash;
}
export default ['$q', lodashAsPromised];

View File

@ -1,6 +1,8 @@
import listGenerator from './list-generator/main';
import title from './title.directive';
import lodashAsPromised from './lodash-as-promised';
export default
angular.module('shared', [listGenerator.name])
.factory('lodashAsPromised', lodashAsPromised)
.directive('title', title);

View File

@ -0,0 +1,75 @@
import 'tower/shared/main';
describe('LodashAsPromised', function() {
var _;
var $q;
function addOne(num) {
return num + 1;
}
function isEven(value) {
return value % 2 === 0;
}
function sum(memo, value) {
return memo + value;
}
beforeEach(module('shared'));
beforeEach(inject(['lodashAsPromised', '$q', function(_lodash, _$q) {
_ = _lodash;
$q = _$q;
}]));
function checkPromiseAndArray(fnName, cb, coll, result) {
context(fnName, function() {
// var itFn = fnName === 'compact' ? it : xit;
var itFn = it;
itFn('works with a promise', function() {
var values = coll.map($q.when);
var methodName = 'then' + _.capitalize(fnName);
var promise;
// _.log('promises for _', values);
if (fnName === 'reduce') {
promise = _[methodName](values, cb, 0);
} else {
promise = _[methodName](values, cb);
}
inject(['$rootScope', function($rootScope) {
setTimeout(function() {
$rootScope.$apply();
}, 1);
}]);
return expect(promise).to.eventually.deep.equal(result);
});
itFn('works with an array', function() {
var value = _[fnName](coll, cb, 0);
expect(value).to.deep.equal(result);
});
});
}
checkPromiseAndArray('map', addOne, [1,2,3,4], [2,3,4,5]);
checkPromiseAndArray('filter', isEven, [1,2,3,4,5,6,7,8], [2,4,6,8]);
checkPromiseAndArray('reduce', sum, [1,2,3,4], 10);
checkPromiseAndArray('pluck', 'blah', [{ blah: 'diddy' }, { blah: 'doo' }], ['diddy', 'doo']);
checkPromiseAndArray('compact', null, ['blah', null, 'diddy', false, 'doo', undefined], ['blah', 'diddy', 'doo']);
checkPromiseAndArray('xor', [4,2], [1,2], [1,4]);
checkPromiseAndArray('groupBy', Math.floor, [4.2,6.1,6.4], { '4': [4.2], '6': [6.1,6.4] } );
it('allows chaining', function() {
function dub(n) { return n * 2; }
var arr = [1,2,3,4].map($q.when);
expect(_(arr).thenMap(dub)).to.eventually.deep.equal([2,4,6,8]);
});
});