给定异步函数的错误处理(try-catch)

问题描述 投票:0回答:2

在下面的代码中,(玩具)函数

f1
f2
来自库,因此我无法更改它们。

function f1() { // cannot change this
   var x;
   alert(x.y); // throws an error because x is undefined
}
function f2() { // cannot change this either
   setTimeout(f1, 1000); // creates an asynchronous timeout
}

现在我想捕获错误:

try { // does not work because of the asynchronous environment
   f2();
} catch (error) {
   console.log('caught: ' + error);
}

但我知道这是行不通的,因为

setTimeout
创建的环境不是为其指定 try-catch 块的环境。

是否有其他可能捕获错误?

javascript asynchronous try-catch
2个回答
0
投票

您可以通过覆盖

f1
功能来做到这一点...

// original functions -- this is all the code you can't modify
function f1() {
  throw "Oh no - an exception!";
}

function f2() {
  try {
    setTimeout(f1, 1000);
  }
  catch(e) {
    alert(e + " - this is handled in the original code");
  }
}
// end of the code you can't modify



// keep a reference to the original f1 function
var __f1 = f1;

// override the original f1 function
var f1 = function() {
  try {
    // this calls the original version of f1(), along with any parameters
    return __f1.apply(this, arguments);
  }
  catch(e) {
    alert(e + " - this is handled in your new code");
  }
};

// execute...
f2();


0
投票

如果感兴趣的封闭第三方功能......在这里

f1
......是可访问的,一种方法/功能修饰符方法,它提供了一个实现功能的抽象层,例如
afterThrowing
afterFinally
,非常方便,将在下一个提供的示例代码中证明...

// closed third party code that can not be changed.
function f1() {
  var x;

  // raises an exception because of an undeclared `x` reference.
  alert(x.y);

  console.log('... should never bee logged.')
}
// closed third party code that can not be changed either.
function f2() {
  // invocation happens deferred/asynchronous.
   setTimeout(f1, 2000);

   console.log('... main thread finished.');
}

function handleThirdPartyInvocationException(exception) {
  const { message, stack } = exception;

  console.log(
    '... handling of following delayed third party function invocation error ...', {
      message, stack
    }
  );
}
// - reassign the accessable third party namespace/reference
//   with a modified, exception handling, version of itself.
f1 = f1.afterThrowing(handleThirdPartyInvocationException);

// - invoke third party main thread.
f2();
.as-console-wrapper { min-height: 100%!important; top: 0; }
<script>
function isFunction(value) {
  return (
    typeof value === 'function' &&
    typeof value.call === 'function' &&
    typeof value.apply === 'function'
  );
}
function getSanitizedTarget(value) {
  return value ?? null;
}

function afterThrowing(handler, target) {
  target = getSanitizedTarget(target);

  const proceed = this;
  return (

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

    function afterThrowingType(...argumentArray) {
      const context = getSanitizedTarget(this) ?? target;

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

      } catch (exception) {

        result = handler.call(context, exception, argumentArray);
      }
      return result;
    }
  ) || proceed;
}
Reflect.defineProperty(Function.prototype, 'afterThrowing', {
  configurable: true,
  writable: true,
  value: afterThrowing,
});
</script>

© www.soinside.com 2019 - 2024. All rights reserved.