Merge pull request #6421 from lcdservices/CRM-16968
[civicrm-core.git] / ang / crmUtil.js
index f64292762bdb1f21d01a01e6aeacd5375c599224..d480279068239cb384be3ad958fa48a798d7af24 100644 (file)
@@ -2,8 +2,8 @@
 (function (angular, $, _) {
   angular.module('crmUtil', []);
 
-  // usage:
-  //   crmApi('Entity', 'action', {...}).then(function(apiResult){...})
+  // Angular implementation of CRM.api3
+  // @link http://wiki.civicrm.org/confluence/display/CRMDOC/AJAX+Interface#AJAXInterface-CRM.api3
   //
   // Note: To mock API results in unit-tests, override crmApi.backend, e.g.
   //   var apiSpy = jasmine.createSpy('crmApi');
@@ -19,7 +19,7 @@
       if (_.isObject(entity)) {
         // eval content is locally generated.
         /*jshint -W061 */
-        p = backend(eval('('+angular.toJson(entity)+')'), message);
+        p = backend(eval('('+angular.toJson(entity)+')'), action);
       } else {
         // eval content is locally generated.
         /*jshint -W061 */
     };
   }]);
 
+  // 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){