0

Reworded:

A common pattern is to pass callback functions, such as with Mongoose's save (just for example and simplified - no error handling):

someMethod(req:Request, res:Response){
    document.save( function(err){ res.status(200).send({message: 'all good'})});
}

I'd like to externalize the callback. You can do this this way:

var respond = function(err:any, res:Response){
    res.status(200).send({message: 'all good'});
}

someMethod(req:Request, res:Response){
    document.save( function(err){ respond(err, res)});
}

...but ideally I'd like to do this by just passing a function like respond without having to create a call back function to enclose respond. I wanted to know if this is possible. Since the anonymous function has access to res, I thought there might be some way to gain access to res in a function defined externally. It appears there is not a way to do this so I'll live with wrapping it.

My original question was trying to isolate the specific issue I was interested in - which is to gain access to the caller's variables implicitly. Doesn't seem like that is possible. Fair enough.

Original Question:

I'd like to externalize a bit of code I use frequently and I'm having trouble understanding closure in the context of a Typescript method. Take a look:

var test = function(){
    console.log("Testing external: "+JSON.stringify(this.req.body));
}

class Handler {

    static post(req: Request, res: Response){
        (function(){
            console.log("TESTING anon: "+JSON.stringify(req.body));
        }) ();
        test();            
    }
}

Besides the fact that this does nothing useful, in this bit of code, the inline anonymous function has access to the req object, but the test() function does not. this in test is undefined. Removing this to match the inline function doesn't help.

I believe if I were to bind on this for the call I'd just end up with a reference to the Handler class when I really want to bind on the post method.

My motivation for doing this is that I want to make a function that can be passed as a callback to a bunch of different request handlers. When I write the functions inline it all works, but when I externalize it I can't get a closure over the variables in the enclosing method. I've read "You Don't Know JS: this & Object Prototypes", and in pure Javascript I can manage to make these sorts of things work but I'm obviously doing something wrong here (it may not be Typescript related, maybe I'm just messing it up).

So bottomline - is there a way I can externalize the handler and get access to the method variables as if I were writing it inline? I could just create an inline anonymous function as the callback that calls the external function with all the variables I need, but I want to really understand what is happening here.

WillyC
  • 3,917
  • 6
  • 35
  • 50
  • Hint: http://stackoverflow.com/questions/4472529/accessing-variables-trapped-by-closure – Jared Smith Nov 15 '16 at 19:11
  • Also, has nothing to do with typescript. – Jared Smith Nov 15 '16 at 19:11
  • I may be missing it but that is kind of the inside out of what I'm trying to do. I'm not trying to extract access to a variable from within a closure, I'm trying to get a closure over the calling method. I'm looking from the inside out, not the outside in. – WillyC Nov 15 '16 at 19:16

1 Answers1

0

This is not an answer, but will hopefully give me enough feedback to give you one because its not at all clear what you're actually trying to accomplish here and whether or not you actually understand what the terms mean is an open question since you use them correctly one minute and sketchily the next.

var test = function(){
    console.log("Testing external: " + JSON.stringify(this.req.body));
}

In strict mode this will throw an error, in sloppy it will try to access the req property of the global object which is not likely what you want.

(function(){
    console.log("TESTING anon: "+JSON.stringify(req.body));
}) ();

The IFFE wrapper is completely unnecessary, it literally adds nothing to the party. So why include it?

static post(req: Request, res: Response){
    console.log("TESTING anon: "+JSON.stringify(req.body));
    test(); // is this the spot where you are 'in-lining?'   
}

What I think you want is this:

var test = function(reqBody) {
    console.log("Testing external: " + JSON.stringify(reqBody));
};

class Handler {
    static post(req: Request, res: Response) {
        test(req.body);
    }         
}
Jared Smith
  • 19,721
  • 5
  • 45
  • 83
  • Its completely unclear what you're asking and there are too many conceptual errors in the snippet you posted to easily unravel. The IIFE will be called at the time the function is defined, but since it hasn't been called the parameters to the function won't be, meaning that the code *should* throw at that point. Dynamic scope? No programming language since elisp has used dynamic scope and while the implicit `this` argument is assigned dynamically assigned based on the calling object there's no scope involved. – Jared Smith Nov 15 '16 at 22:03