I know it's maybe an fairly easy basic knowledge for you, here I need to ask your help to see whether there is a 'hole' behind to improve. Please check the code below, can I set 'response' as callback parameter but not callSvc's? instead of this kinda 'tricky' way?
function callSvc(response, callback){
callback(response);
}
callSvc("I'm a response!",function(param_response){document.write(param_response);});
Thanks..
Update
Maybe this is good enough?
function callSvc(callback) {
callback("response");
}
callSvc(function(data) {
document.write(arguments[0]);
});
There shouldn't be anything tricky about closures in javascript. They are a language feature.
You can avoid the wrapping callSvc function as well, and jump straight into this:
var response = "I'm a response"
var callback = function(){document.write(response);};
The callback function can "see" response as if you passed it as a parameter, since it forms a closure.
callback(); //I'm a response
Eh? All that code looks to be the equivalent of
document.write("I'm a response!");
So you can bypass all the methods. You can also declare an anonymous function and call it immediately, if that's what you wanted to do:
(function(param_response){document.write(param_response);})("I'm a response!");
Or lastly, if you need to pass parameters to a callback that doesn't except any, then wrap it in an anonymous funciton
func_that_takes_callback(function(){the_real_callback(arg);});
Instead of defining your callback anonymously define it before hand:
function callSvc(response, callback){
callback(response);
}
function cb(param_response) {
document.write(param_response);
}
Then you can use it in a call to callSvc or on its own:
callSvc("I'm a response!", cb);
cb("I'm a response!");
Related
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.
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);
}
}
I have the following call to a Javascript promise:
deleteDatabase().then(function () {
doSomeStuff();
}, function (err) {
processError(err);
});
It works fine, but it looks really wordy. Is there a way to have a terser way to do this? Maybe something like this (which does not seem to work):
deleteDatabase().then(doSomeStuff(), processError(err));
You need to pass a function, not the result of calling them:
deleteDatabase().then(doSomeStuff, processError);
Of course, this will pass the result of the deleteDatabase() action to your doSomeStuff function, so if you expect it to get no arguments you will need to use the function expression as you did.
You have an issue with the syntax
deleteDatabase().then(doSomeStuff, processError);
if you put () after the function name it will call it immediately, by omitting the parenthesis you are passing a reference to the function and asking for it to be called at some point later on by the promise.
I don't understand why some JavaScript frameworks like ember.js use an anonymous function as a function parameter value. I would understand if the function was returning something, but it is not.
Here is a sample code of the routing system of ember.js that demonstrate my question:
App.Router.map(function() {
this.route("about", { path: "/about" });
this.route("favorites", { path: "/favs" });
});
Please explain me why this code creates an anonymous function as a parameter.
It's because that function .map is an async function, and that anonymous function is what to run AFTER .map completes.
Typically async functions look like:
function async(callback) {
//async stuff, yada
callback();
}
That callback is what you pass in to run once the async operations complete
So basically this creates a way to encapsulate functionality, and run the route set up w/e they need to. I'm not 100% familiar with amber, but my guess is that they do some setup and checking/validation before initializing the routes. Because you pass in the anonymous function, they can now defer the set up you specify until everything is set and ready to go!
A function passed in as a parameter means that the function will be run at some point during (or at the end of) the outer function. Often this is used to pass in a callback function.
For example, the map method might do some stuff and then call the anonymous function when finished:
function map(function) {
// Do some stuff
function();
}
I'm trying to build an API in JS that will perform some operations and then execute the callback that's registered in AS when it's done. Because it's an API, I am just providing a JS method signature for another developer to call in Flash. Thus, the callback name that's registered in the AS part of the code should be a parameter that's passed in to the JS API in order for JS to communicate back to Flash.
For example:
[AS3 code]
ExternalInterface.addCallback("flashCallbackName", processRequest);
ExternalInterface.call("namespace.jsFnToCall", flashCallbackName);
function processRequest(data:String):void
{
//do stuff
}
[JS code]
var namespace =
{
jsFnToCall: function(callback)
{
//Do stuff in this function and then fire the callback when done.
//getFlashMovie is just a util function that grabs the
//Flash element via the DOM; assume "flash_id"'s a global var
//Below does not work...it's what I'd be ideally be doing some how.
getFlashMovie(flash_id).callback(data);
}
};
Because the definition of the function is in AS, I can't use the window[function name] approach. The only way I can think of is to build the callback in a string and then use the eval() to execute it.
Suggestions? T.I.A.
Well, I can think of one thing I would try, and one thing that would work.
What I would try first.
getFlashMovie(flash_id)['callback'](data);
What would work: Have the callback always be the same, say callback. The first parameter to the callback could be used to determine what actual function to call in flash. For example:
function callback($fn:String, $data:*) {
// either
this[$fn]($data);
// or
switch ($fn) {
case "callback1":
DoSomeCallback($data);
break;
}
Additionally passing the objectID makes it a bit simpler:
ExternalInterface.addCallback("flashCallbackName", processRequest);
ExternalInterface.call("namespace.jsFnToCall", ExternalInterface.objectID, "flashCallbackName");
Then in your JS:
var namespace =
{
jsFnToCall: function(objectID, callback)
{
//Do stuff in this function and then fire the callback when done.
document[objectID][callback](data);
}
};
I'm fairly new to the callback-style of programming in javascript.
Is there a way to force code to wait until a function call finishes via a callback?
Let me explain.
The following function takes a number and returns a result based upon it.
function get_expensive_thing(n) {
return fetch_from_disk(n);
}
So far, easy enough.
But what do I do when fetch_from_disk instead returns its result via a callback?
Like so:
function get_expensive_thing(n) {
fetch_from_disk(n, function(answer) {
return answer; // Does not work
});
}
The above doesn't work because the return is in the scope of the anonymous function,
rather than the get_expensive_thing function.
There are two possible "solutions", but both are inadequate.
One is to refactor get_expensive_thing to itself answer with a callback:
function get_expensive_thing(n, callback) {
fetch_from_disk(n, function(answer) {
callback(answer);
});
}
The other is to recode fetch_from_disk, but this is not an option.
How can we achieve the desired result
while keeping the desired behaviour of get_expensive_thing
-- i.e., wait until fetch_from_disk calls the callback, then return that answer?
Pretty much there's no "waiting" in browser Javascript. It's all about callbacks. Remember that your callbacks can be "closures", which means definitions of functions that "capture" local variables from the context in which they were created.
You'll be a happier person if you embrace this way of doing things.
add in that missing return :)
function get_expensive_thing(n) {
return fetch_from_disk(n, function(answer) {
return answer;
});
}