ANZR
ANZR

Reputation: 91

How to use common try-catch for processing every given function in Javascript?

These are some of my functions, I need to write a common function to see if functions are running without error. I tried with try/catch method. But I could only do that individually on each function.

function fisrt(){
 console.log("First");
};

function second(){
 console.log("Second");
}

function third(){
 console.log("Third");
}
fisrt();
second();
third();

I was writing each function inside the try-catch. Is there a way I can write a common try-catch for all the functions.

try {
     (function first() {
       console.log("ffgdf")
    })();

 }catch (e) {
      console.log( "won't work" );
    }

Upvotes: 4

Views: 3263

Answers (3)

Alisson Zampietro
Alisson Zampietro

Reputation: 111

In case of you wishing to get a "throwed" exception, you can use the Promise.all.

function parent() {
    function first() {
        console.log('First');
        throw new Error('First error');
    }
    
    function second() {
        console.log('Second');
    }
    
    function third() {
        console.log('Third');
    }
    
    return Promise.all([
        first(),
        second(),
        third(),
    ])
}

parent()
     .then(result => console.log(result))
     .catch(error => console.error(error))

Upvotes: 1

Peter Seliger
Peter Seliger

Reputation: 13396

Regarding the introducing sentence of the accepted answer two years ago ...

You could define a wrapper function, that takes your desired function as a parameter, and wraps it in a try catch.

... this part could be covered with (an) abstraction(s) where one also can provide the (different) handling of an invocation failure (the catch and exception clause).

If one does, for instance, provide functionality that wraps a function/method in way that does not only provide the try catch but also takes the exception handling into account, one can easily accomplish tasks, like the one asked by the OP for, which are mainly about programmable approaches for automatically creating and processing lists of functions/methods that are going to be invoked whilst suppressing unintended/unexpected invocation failures.

The following example does implement afterThrowing and afterFinally, two method modifier methods, each processing the original function/method with an exception handler as its first argument.

Making use of the provided abstraction(s) the approach itself boils down to writing reduce functionality which processes an array of functions by invoking each function with its own set of arguments and collecting its invocation success state ...

function first(...args) {
  console.log("first :: does succeed :: argsList :", args);
  return args.join(', ');
}
function second(...args) {
  console.log("second :: going to fail :: argsList :", args);
  throw new Error('2nd invocation failed.');
}
function third(...args) {
  console.log("third :: going to fail :: argsList :", args);
  throw new Error('3rd invocation failed.');
}
function fourth(...args) {
  console.log("fourth :: does succeed :: argsList :", args);
  return args.join(', ');
}
function fifth(...args) {
  console.log("fifth :: does succeed :: argsList :", args);
  return args.join(', ');
}


/**
 *  reduce functionality which processes an array of functions.
 */
function collectResultAfterThrowing(collector, fct, idx) {
  function afterThrowingHandler(error, argsArray) {
    // - can access the try-catch exception and the arguments
    //   that have been passed prior to the invocation failure.
    return {
      success: false,
      failure: {
        message: error.toString(),
        argsList: Array.from(argsArray)
      }
    }
  }
  function unifyResult(value) {
    return ((
         value
      && value.hasOwnProperty('success')
      && (value.success === false)
      && value
    ) || { success: true, value });
  }
  collector.results.push(
    unifyResult(fct                         // - modify original function towards an
      .afterThrowing(afterThrowingHandler)  //   `afterThrowing` handling of its try-catch result(s).
      .apply(null, collector.listOfArguments[idx])
    )
    // - an `afterThrowing` modified function does always return either the result of the
    //   original function's invocation or the return value of its 'afterThrowing' handler.
  );
  return collector;
}


/**
 *  reduce functionality which processes an array of functions.
 */
function collectResultAfterFinally(collector, fct, idx) {
  function isError(type) {
    return (/^\[object\s+Error\]$/).test(Object.prototype.toString.call(type));
  }
  function createResult(value) {
    return (isError(value) && {
      success: false,
      message: value.toString()
    } || {
      success: true,
      value
    });
  }
  collector.results.push(
    createResult(fct            // - modify original function towards an
      .afterFinally(() => null) //   `afterFinally` handling of its try-catch result(s).
      .apply(null, collector.listOfArguments[idx])
    )
    // - an `afterFinally` modified function does always return either the result of the
    //   original function's invocation or the try-catch exception of the invocation attempt.
  );
  return collector;
}


// ... two times, each the actual task, 
// ... once based on "afterThrowing" and
// ... once based on "afterFinally" ...

console.log('"afterThrowing" based try-and-catch results :', [

    first,
    second,
    third,
    fourth,
    fifth

  ].reduce(collectResultAfterThrowing, {

    listOfArguments: [
      ['foo', 'bar'],
      ['baz', 'biz'],
      ['buz', 'foo'],
      ['bar', 'baz'],
      ['biz', 'buz']
    ],
    results: []

  }).results
);
console.log('\n\n\n');

console.log('"afterFinally" based try-and-catch results :', [

    first,
    second,
    third,
    fourth,
    fifth

  ].reduce(collectResultAfterFinally, {

    listOfArguments: [
      ['foo', 'bar'],
      ['baz', 'biz'],
      ['buz', 'foo'],
      ['bar', 'baz'],
      ['biz', 'buz']
    ],
    results: []

  }).results
);
.as-console-wrapper { min-height: 100%!important; top: 0; }
<script>
  (function (Function) {

    const fctPrototype = Function.prototype;
    const FUNCTION_TYPE = (typeof Function);

    function isFunction(type) {
      return (
           (typeof type == FUNCTION_TYPE)
        && (typeof type.call == FUNCTION_TYPE)
        && (typeof type.apply == FUNCTION_TYPE)
      );
    }
    function getSanitizedTarget(target) {
      return ((target != null) && target) || null;
    }

    function afterThrowing/*Modifier*/(handler, target) {
      target = getSanitizedTarget(target);

      const proceed = this;
      return (

        isFunction(handler) &&
        isFunction(proceed) &&

        function () {
          const context = target || getSanitizedTarget(this);
          const args = arguments;

          let result;
          try {
            result = proceed.apply(context, args);

          } catch (exception) {

            result = handler.call(context, exception, args);
          }
          return result;
        }

      ) || proceed;
    }
    // afterThrowing.toString = () => 'afterThrowing() { [native code] }';

    function afterFinally/*Modifier*/(handler, target) {
      target = getSanitizedTarget(target);

      const proceed = this;
      return (

        isFunction(handler) &&
        isFunction(proceed) &&

        function () {
          const context = target || getSanitizedTarget(this);
          const args = arguments;

          let result, error;
          try {
            result = proceed.apply(context, args);

          } catch (exception) {

            error = exception;

          } // finally { ... }

          result = (error || result);
          handler.call(context, result, args);

          return result;
        }

      ) || proceed;
    }
    // afterFinally.toString = () => 'afterFinally() { [native code] }';

    Object.defineProperty(fctPrototype, 'afterThrowing', {
      configurable: true,
      writable: true,
      value: afterThrowing/*Modifier*/
    });

    Object.defineProperty(fctPrototype, 'afterFinally', {
      configurable: true,
      writable: true,
      value: afterFinally/*Modifier*/
    });

  }(Function));
</script>

Upvotes: 1

Steve Vaughan
Steve Vaughan

Reputation: 2189

You could define a wrapper function, that takes your desired function as a parameter, and wraps it in a try catch.

function wrapper(fn) {
    try {
        fn();
    } catch(error) {
        console.error(error);
    }
}

Then given your original functions:

function first() {
    console.log("First");
};

function second() {
    console.log("Second");
}

function third() {
    console.log("Third");
}

You can test each one by using your wrapper function:

wrapper(first);
wrapper(second);
wrapper(third);

Without needing to add try catch to each function.

Upvotes: 6

Related Questions