CRM-20600 - Angular deps - Move from *.js to *.php
[civicrm-core.git] / ang / crmUtil.js
index 8cb6242689a559b5027862bffdcd8c816e7147ec..a8b0370ad409aa7f3936b9181bba09dbe984146f 100644 (file)
@@ -1,6 +1,6 @@
 /// crmUi: Sundry UI helpers
 (function (angular, $, _) {
-  angular.module('crmUtil', []);
+  angular.module('crmUtil', CRM.angRequires('crmUtil'));
 
   // Angular implementation of CRM.api3
   // @link http://wiki.civicrm.org/confluence/display/CRMDOC/AJAX+Interface#AJAXInterface-CRM.api3
     };
   });
 
+  // Run a given function. If it is already running, wait for it to finish before running again.
+  // If multiple requests are made before the first request finishes, all but the last will be ignored.
+  // This prevents overwhelming the server with redundant queries during e.g. an autocomplete search while the user types.
+  // Given function should return an angular promise. crmThrottle will deliver the contents when resolved.
+  angular.module('crmUtil').factory('crmThrottle', function($q) {
+    var pending = [],
+      executing = [];
+    return function(func) {
+      var deferred = $q.defer();
+
+      function checkResult(result, success) {
+        _.pull(executing, func);
+        if (_.includes(pending, func)) {
+          runNext();
+        } else if (success) {
+          deferred.resolve(result);
+        } else {
+          deferred.reject(result);
+        }
+      }
+
+      function runNext() {
+        executing.push(func);
+        _.pull(pending, func);
+        func().then(function(result) {
+          checkResult(result, true);
+        }, function(result) {
+          checkResult(result, false);
+        });
+      }
+
+      if (!_.includes(executing, func)) {
+        runNext();
+      } else if (!_.includes(pending, func)) {
+        pending.push(func);
+      }
+      return deferred.promise;
+    };
+  });
+
 })(angular, CRM.$, CRM._);