Spaces:
Sleeping
Sleeping
| ; | |
| 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; | |
| } | |
| }; | |
| } | |