};
}]);
+ // Wrap an async function in a queue, ensuring that independent async calls are issued in strict sequence.
+ // usage: qApi = crmQueue(crmApi); qApi(entity,action,...).then(...); qApi(entity2,action2,...).then(...);
+ // This is similar to promise-chaining, but allows chaining independent procs (without explicitly sharing promises).
+ angular.module('crmUtil').factory('crmQueue', function($q) {
+ // @param worker A function which generates promises
+ return function crmQueue(worker) {
+ var queue = [];
+ function next() {
+ var task = queue[0];
+ worker.apply(null, task.a).then(
+ function onOk(data) {
+ queue.shift();
+ task.dfr.resolve(data);
+ if (queue.length > 0) next();
+ },
+ function onErr(err) {
+ queue.shift();
+ task.dfr.reject(err);
+ if (queue.length > 0) next();
+ }
+ );
+ }
+ function enqueue() {
+ var dfr = $q.defer();
+ queue.push({a: arguments, dfr: dfr});
+ if (queue.length === 1) {
+ next();
+ }
+ return dfr.promise;
+ }
+ return enqueue;
+ };
+ });
+
// Adapter for CRM.status which supports Angular promises (instead of jQuery promises)
// example: crmStatus('Saving', crmApi(...)).then(function(result){...})
angular.module('crmUtil').factory('crmStatus', function($q){
});
});
+
+ describe('crmQueue', function() {
+ var crmQueue, $q, $rootScope, $timeout;
+
+ beforeEach(inject(function(_crmQueue_, _$rootScope_, _$q_, _$timeout_) {
+ crmQueue = _crmQueue_;
+ $rootScope = _$rootScope_;
+ $q = _$q_;
+ $timeout = _$timeout_;
+ }));
+
+ function addAfterTimeout(a, b, ms) {
+ var dfr = $q.defer();
+ $timeout(function(){
+ dfr.resolve(a+b);
+ }, ms);
+ return dfr.promise;
+ }
+
+ it('returns in order', function(done) {
+ var last = null;
+ var queuedFunc = crmQueue(addAfterTimeout);
+ // note: the queueing order is more important the timeout-durations (15ms vs 5ms)
+ queuedFunc(1, 2, 25).then(function(sum) {
+ expect(last).toBe(null);
+ expect(sum).toBe(3);
+ last = sum;
+ });
+ queuedFunc(3, 4, 5).then(function(sum){
+ expect(last).toBe(3);
+ expect(sum).toBe(7);
+ last = sum;
+ done();
+ });
+
+ for (var i = 0; i < 5; i++) {
+ $rootScope.$apply();
+ $timeout.flush(20);
+ }
+ });
+ });
+
});