Merge pull request #9586 from alifrumin/caselinks
[civicrm-core.git] / ang / crmUtil.js
index 8cb6242689a559b5027862bffdcd8c816e7147ec..c48b2cbc54ea3e4510ebc8748d498769560ece45 100644 (file)
     };
   });
 
+  // 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._);