aboutsummaryrefslogtreecommitdiff
path: root/node_modules/@mrmlnc/readdir-enhanced/lib/call.js
diff options
context:
space:
mode:
Diffstat (limited to 'node_modules/@mrmlnc/readdir-enhanced/lib/call.js')
-rw-r--r--node_modules/@mrmlnc/readdir-enhanced/lib/call.js54
1 files changed, 54 insertions, 0 deletions
diff --git a/node_modules/@mrmlnc/readdir-enhanced/lib/call.js b/node_modules/@mrmlnc/readdir-enhanced/lib/call.js
new file mode 100644
index 0000000..07e3d84
--- /dev/null
+++ b/node_modules/@mrmlnc/readdir-enhanced/lib/call.js
@@ -0,0 +1,54 @@
+'use strict';
+
+let call = module.exports = {
+ safe: safeCall,
+ once: callOnce,
+};
+
+/**
+ * Calls a function with the given arguments, and ensures that the error-first callback is _always_
+ * invoked exactly once, even if the function throws an error.
+ *
+ * @param {function} fn - The function to invoke
+ * @param {...*} args - The arguments to pass to the function. The final argument must be a callback function.
+ */
+function safeCall (fn, args) {
+ // Get the function arguments as an array
+ args = Array.prototype.slice.call(arguments, 1);
+
+ // Replace the callback function with a wrapper that ensures it will only be called once
+ let callback = call.once(args.pop());
+ args.push(callback);
+
+ try {
+ fn.apply(null, args);
+ }
+ catch (err) {
+ callback(err);
+ }
+}
+
+/**
+ * Returns a wrapper function that ensures the given callback function is only called once.
+ * Subsequent calls are ignored, unless the first argument is an Error, in which case the
+ * error is thrown.
+ *
+ * @param {function} fn - The function that should only be called once
+ * @returns {function}
+ */
+function callOnce (fn) {
+ let fulfilled = false;
+
+ return function onceWrapper (err) {
+ if (!fulfilled) {
+ fulfilled = true;
+ return fn.apply(this, arguments);
+ }
+ else if (err) {
+ // The callback has already been called, but now an error has occurred
+ // (most likely inside the callback function). So re-throw the error,
+ // so it gets handled further up the call stack
+ throw err;
+ }
+ };
+}