1

I need to override some behaviour of function, that goes after it calls other function. The problem is that this parent function is a library and I dont want to change it, so solutions like make some flag or another change of this function is not so good. I know that I got an caller object in function that I can change, so maybe I can figure out smth with it. Heres the example:

function parent()
{
  console.log("some need stuff");
  some.handler.function.from.config.that.i.can.change();
  console.log("need omit this right till the end");
}

function child()
{
  console.log("need to somehow stop evaluation of " + child.caller + " function");
}

As a ruby programmer I know there is lambdas with which you can terminate evaluation from inner scope of closure. But Im not sure how to do this from javascript.

sandric
  • 2,310
  • 3
  • 21
  • 26
  • I've posted a possible solution to your problem, however - I think that it's as good as it gets with your requirements. However, doing what I suggested usually is not the best approach. I suspect [the XY problem](http://meta.stackexchange.com/questions/66377/what-is-the-xy-problem). If there is a more specific issue you're facing here, please consider opening a new question with the actual problem. Using exceptions for this is strongly discouraged. – Benjamin Gruenbaum Jun 29 '13 at 19:26
  • you can always throw, but async techniques are preferred when possible. – dandavis Jun 29 '13 at 21:19

3 Answers3

8

You can't do that directly. (Moreover .caller is obsolete)

You can however use a dirty trick:

try{
    parentFunction();//calls child
}catch(e){
   //done
}

function child(){
    doWhatever();
    throw new Error("this will hopefully propagate");
}

Fiddle

This will only work assuming the parent does not catch exceptions itself when calling the child.

Moreover, it is generally a bad idea to use exceptions for flow control. Use this as a last resort.

Benjamin Gruenbaum
  • 270,886
  • 87
  • 504
  • 504
1

Call a new function that you do control before you call the library, and wrap the call to the library you cannot modify in a try/catch block.

For example:

function meta-parent()
{
  try {
    parent();
  }
  catch (e){
      // don't really be empty!
  }
}

function parent()
{
  console.log("some need stuff");
  some.handler.function.from.config.that.i.can.change();
  // Nothing below here will run because of your child's exception
  console.log("need omit this right till the end");  
}

function child()
{
  console.log("need to somehow stop evaluation of " + child.caller + " function");
  throw new Error(); //breakout!
}

Note inspiration: Breaking a parent function from within a child function (PHP Preferrably)

Community
  • 1
  • 1
James
  • 576
  • 2
  • 5
  • 2
    How is this any different from my solution from 8 minutes ago? – Benjamin Gruenbaum Jun 29 '13 at 19:26
  • @Benjamin. No significant difference; you just typed more quickly but after I had started, so I didn't know there was an answer already posted when I clicked. (You can probably tell I'm new here...should I delete the extraneous answer?) – James Jun 29 '13 at 19:32
  • James, your answer is perfectly fine and your explanation to why you added it seems reasonable. I'm not asking you to delete it (nor is anyone else). If you think it's useful given mine - you're very welcome to keep it here. – Benjamin Gruenbaum Jun 29 '13 at 20:55
0

As Benjamin Gruenbaum points out, the use of exceptions for flow control should be regarded as a last resort, however does the Promises/A proposal (in some implementations) not legitimize such exploitation of exceptions in this way?

I do take on board that an (otherwise uncaught) error thrown from a child function is maybe not what the Promises/A authors had in mind (ie we're still arguably talking about a "dirty trick"), however the Promises/A proposal doesn't specifically exclude such error propagation either.

The Q lib would be ideal for this problem, allowing something like this :

Q.fcall(parentFunction).then(function (value) {
    alert(value);
}, function (error) {
    alert(error);
});

fiddle

Please note that, for convenience, I also use jQuery in the fiddle but only to give functionality to the buttons.

Beetroot-Beetroot
  • 18,022
  • 3
  • 37
  • 44
  • Having co-routines (with the `yield`) keyword would allow you to use regular try/catch (see Q.async !) . While resolve/reject are similar to try/catch (and often represent the same thing, for example, an ajax failing seems appropriate for a 'catch' clause) they are not exactly identical conceptually (p.s I even [implemented asynchronous catch for node for fun :)](http://stackoverflow.com/questions/14301839/javascript-asynchronous-exception-handling-with-node-js) for fun with promise-like syntax. The point you raise is valid and interesting though. – Benjamin Gruenbaum Jun 29 '13 at 20:49
  • Anyway, I think this answer on its own would be an interesting question on programmers.stackexchange.com . As it currently stands, it does not attempt to answer op's question. I think that an independent question on programmers would both be where it belongs, and get it attention from other developers as well. – Benjamin Gruenbaum Jun 29 '13 at 20:50