summaryrefslogtreecommitdiffstats
path: root/toolkit/jetpack/sdk/lang/functional/concurrent.js
diff options
context:
space:
mode:
Diffstat (limited to 'toolkit/jetpack/sdk/lang/functional/concurrent.js')
-rw-r--r--toolkit/jetpack/sdk/lang/functional/concurrent.js110
1 files changed, 110 insertions, 0 deletions
diff --git a/toolkit/jetpack/sdk/lang/functional/concurrent.js b/toolkit/jetpack/sdk/lang/functional/concurrent.js
new file mode 100644
index 000000000..85e8cff46
--- /dev/null
+++ b/toolkit/jetpack/sdk/lang/functional/concurrent.js
@@ -0,0 +1,110 @@
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+// Disclaimer: Some of the functions in this module implement APIs from
+// Jeremy Ashkenas's http://underscorejs.org/ library and all credits for
+// those goes to him.
+
+"use strict";
+
+module.metadata = {
+ "stability": "unstable"
+};
+
+const { arity, name, derive, invoke } = require("./helpers");
+const { setTimeout, clearTimeout, setImmediate } = require("../../timers");
+
+/**
+ * Takes a function and returns a wrapped one instead, calling which will call
+ * original function in the next turn of event loop. This is basically utility
+ * to do `setImmediate(function() { ... })`, with a difference that returned
+ * function is reused, instead of creating a new one each time. This also allows
+ * to use this functions as event listeners.
+ */
+const defer = f => derive(function(...args) {
+ setImmediate(invoke, f, args, this);
+}, f);
+exports.defer = defer;
+// Exporting `remit` alias as `defer` may conflict with promises.
+exports.remit = defer;
+
+/**
+ * Much like setTimeout, invokes function after wait milliseconds. If you pass
+ * the optional arguments, they will be forwarded on to the function when it is
+ * invoked.
+ */
+const delay = function delay(f, ms, ...args) {
+ setTimeout(() => f.apply(this, args), ms);
+};
+exports.delay = delay;
+
+/**
+ * From underscore's `_.debounce`
+ * http://underscorejs.org
+ * (c) 2009-2014 Jeremy Ashkenas, DocumentCloud and Investigative Reporters & Editors
+ * Underscore may be freely distributed under the MIT license.
+ */
+const debounce = function debounce (fn, wait) {
+ let timeout, args, context, timestamp, result;
+
+ let later = function () {
+ let last = Date.now() - timestamp;
+ if (last < wait) {
+ timeout = setTimeout(later, wait - last);
+ } else {
+ timeout = null;
+ result = fn.apply(context, args);
+ context = args = null;
+ }
+ };
+
+ return function (...aArgs) {
+ context = this;
+ args = aArgs;
+ timestamp = Date.now();
+ if (!timeout) {
+ timeout = setTimeout(later, wait);
+ }
+
+ return result;
+ };
+};
+exports.debounce = debounce;
+
+/**
+ * From underscore's `_.throttle`
+ * http://underscorejs.org
+ * (c) 2009-2014 Jeremy Ashkenas, DocumentCloud and Investigative Reporters & Editors
+ * Underscore may be freely distributed under the MIT license.
+ */
+const throttle = function throttle (func, wait, options) {
+ let context, args, result;
+ let timeout = null;
+ let previous = 0;
+ options || (options = {});
+ let later = function() {
+ previous = options.leading === false ? 0 : Date.now();
+ timeout = null;
+ result = func.apply(context, args);
+ context = args = null;
+ };
+ return function() {
+ let now = Date.now();
+ if (!previous && options.leading === false) previous = now;
+ let remaining = wait - (now - previous);
+ context = this;
+ args = arguments;
+ if (remaining <= 0) {
+ clearTimeout(timeout);
+ timeout = null;
+ previous = now;
+ result = func.apply(context, args);
+ context = args = null;
+ } else if (!timeout && options.trailing !== false) {
+ timeout = setTimeout(later, remaining);
+ }
+ return result;
+ };
+};
+exports.throttle = throttle;