有没有办法在函数中注入try catch?

时间:2014-07-23 13:24:06

标签: javascript aop function-composition method-modifier

也许你们中的一些人知道AOP,在某些语言中使用AOP可以使你能够在方法执行之前,之前或之后注入代码等。

我想要的是在Javascript中应用相同的内容,我目前正在开发一个包含超过300个ajax调用的大型应用程序,每次我需要对它们的catch语句进行一些更改时,我必须修改他们一个接一个,非常乏味。

我想做的是:

functionName.before("try {")

functionName.after("} catch(ex){
//dostuff
}")

有可能吗?我知道有些东西像.call,或者每个函数里面的参数对象......它们看起来很漂亮的元功能(AOP)功能。

4 个答案:

答案 0 :(得分:2)

不在beforeafter,但wrap会有效:

Function.prototype.wrapTry = function(handle) {
    var fn = this;
    return function() {
        try {
            return fn.apply(this, arguments);
        } catch(e) {
            return handle(e);
        }
    };
};

然后像

一样使用它
var safeFunction = functionName.wrapTry(doStuff);

答案 1 :(得分:0)

在JavaScript中,函数是第一类对象。这意味着你可以操纵或重新声明它们。

假设有一个" foo"功能:

var originalFoo = foo;
foo = function()
{
    // "before" code.

    // Call the original function.
    originalFoo.apply(this, arguments);

    // "after" code.
};

之后,对foo()的任何调用都将调用新函数:即使使用参数。

答案 2 :(得分:0)

旧问题,但您可以查看此https://github.com/k1r0s/kaop-ts/blob/master/docs/api.md#available-join-points

$params = array(
  'x-api-key' => 'xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx',
  'Accept' => 'application/json'
);
$fields =  array(
  "lastName" => $entries[$tmp_id]["2.6"],
  "firstName" => $entries[$tmp_id]["2.3"],
  "webAddresses" => array([
    "value" => $entries[$tmp_id]["4"]
  ]),
  "phoneNumbers" => array([
    "value" => $entries[$tmp_id]["5"]
  ])
);

$success = $client->CallAPI(
  'https://myurl.com/v2/api',
  'POST', $fields, array('FailOnAccessError'=>true, 'RequestHeaders' => $params,'RequestContentType' => 'application/json', 'FollowRedirection' => true, ), $user);

答案 3 :(得分:0)

我也会给出一个迟到的答案,以便对这个特殊情况有所了解,每一个现在都会弹出 JavaScript和AOP

首先,像OP提出的那样的案例总是要求修改已经存在的功能,因此针对封闭的代码,有时甚至不会被认为自己因修改此类代码的控制流而受到挑战的一方拥有。

为什么然后,不只是将其命名为... JavaScript方法修改 JavaScript方法修饰符

其次,由于已经掌握了术语,因此改变JavaScript中的封闭功能与 面向方面编程 无关,除非声称为< strong> AO 至少为 Aspect 提供抽象和代码重用级别, 建议 Pointcut

最后,对于OP将要实现的目标以及已接受的答案,确实存在大量beforeafter around / {{1}解决方案,几乎总是遗憾地提到 AO(P),并且在很多情况下没有处理上下文wrap这对于至关重要>方法修改

我提供的示例使用target的原型实现。由于JavaScript已经具有标准化的afterThrowing,因此我坚信bind对于其他一些方法修饰符也是正确的。 例如Function.prototypebeforeafteraroundafterThrowing

&#13;
&#13;
afterFinally
&#13;
(function (Function) {
  var
    isFunction = function (type) {
      return (
           (typeof type == "function")
        && (typeof type.call == "function")
        && (typeof type.apply == "function")
      );
    },
    getSanitizedTarget = function (target) {
    //return (target == null) ? null : target;
      return ((target != null) && target) || null;
    }
  ;
  Function.prototype.afterThrowing = function (handler, target) { // afterThrowing
    target  = getSanitizedTarget(target);
    var proceed = this ;

    return (isFunction(handler) && isFunction(proceed) && function () {
      var ret, args = arguments;
      try {
        ret = proceed.apply(target, args);
      } catch (exc) {
        ret = handler.call(target, exc, args);
      //throw exc;
      }
      return ret;

    }) || proceed;
  };
}(Function));


// OP's example pseudo code
//
// functionName.before("try {")
//
// functionName.after("} catch(ex){
//   dostuff
// }")

function doStuffAfterThrowing(exception, originalArguments) {
  "use strict";
  var context = this;

  console.log('context : ', context);
  console.log('exception : ', exception);
  console.log('originalArguments : ', originalArguments);

  return "safely handled exception";
}


function doFail() {
  throw (new ReferenceError);
}
function oneOutOfManyAjaxCallbacks(payload) {
  doFail();
}
var jsonData = {
  "foo": "foo",
  "bar": "bar"
};


var someModifiedAjaxCallback = oneOutOfManyAjaxCallbacks.afterThrowing(doStuffAfterThrowing);

// does fail controlled/handled.
console.log('someModifiedAjaxCallback(jsonData) : ', someModifiedAjaxCallback(jsonData));

// does fail "Uncaught".
console.log('oneOutOfManyAjaxCallbacks(jsonData) : ', oneOutOfManyAjaxCallbacks(jsonData));
&#13;
&#13;
&#13;

到目前为止,人们也可以考虑阅读......