I've recently used a nice library for node.js called Kue.
I wanted to get some better understanding of what's going so I started reading the code...
I stumbled on to a piece of code and my mind went "WTF!!?!#$#!$"...
This is the code:
function get(obj) {
var pending = 0
, res = {}
, callback
, done;
return function _(arg){
switch (typeof arg) {
case 'function':
callback = arg;
break;
case 'string':
++pending;
obj[arg](function(err, val){
if (done) return;
if (err) return done = true, callback(err);
res[arg] = val;
--pending || callback(null, res);
});
break;
}
return _;
};
}
which being used like this:
exports.stats = function(req, res){
get(queue)
('inactiveCount')
('completeCount')
('activeCount')
('failedCount')
('delayedCount')
('workTime')
(function(err, obj){
if (err) return res.send({ error: err.message });
res.send(obj);
});
};
.
.
.
Are those functions on functions?!
How are they aware of each other?
What is that '_'(underscore) on the 7th row of the function?
Could someone please help me understad what's goin' on over there? :)
Functions can indeed return functions. Take this function, for example:
function func(text) {
alert(text);
return func;
}
Obviously the return value of any invocation of func will be, again, func, so you can use it like this:
func("hello")("world");
…and you'll get two alerts: first "hello", and then "world".
Next, there's something called a named function expression. You might have seen anonymous function expressions before:
doSomething(thing, function(err) {
// operation completed or something
});
That, of course, is great for simple things, but sometimes you want the function to have a name so it can refer to itself. As Kolink mentioned, if you just want to recurse, there's arguments.callee, which refers to the function currently executing, but there is another way: you can give the function a name visible only within the function while still having it be a function expression:
doSomething(thing, function myself(err) {
// ^^^^^^
// now I can refer to myself as myself!
});
An underscore is a valid identifier, so they're basically just combining these techniques in a way that may be difficult to understand.
Related
Well, is it possible to use function as return statement in outer function?
I want to use something like this:
function returnFunction(){
// some magic (unknown for me) code here
}
// and here is just usual function
function calculateFunction(a,b){
var result = a + b;
returnFunction();
showResult(result);
}
So, the function above should only calculate "a + b" but don't show it result because "returnFunction" should play a role of native "return" statement in "calculateFunction".
I know that I can always do something like this:
function calculateFunction(a,b){
var result = a + b;
if( needReturnFunction() ) return;
showResult(result); // won't run if above true
}
But my point is to actually simulate "return", replace it.
So, if it possible, what the "magic code" then?
The only way I can imagine something like that is if you throw
function returnFunction(){
if (shouldReturn) throw 'return';
}
// and here is just usual function
function calculateFunction(a,b){
var result = a + b;
returnFunction();
showResult(result); // won't run if above throws
}
But then you would have to always use try, catch:
try {
calculateFunction(a, b);
}
catch (err) {
// if error thrown is 'return' then ignore
if (err !== 'return') throw err;
}
This is definitely not something nice to do. You should probably re-think your code.
This question already has answers here:
Javascript callback - how to return the result?
(3 answers)
Closed 8 years ago.
This is a noob JS question that I can't quite verbalize well enough to successfully Google.
function getUser(username){
var toReturn = { };
Restangular.one('users', username).get().then(function(result){
toReturn = result;
});
return toReturn //doesn't work
}
Restangular.one(...).get() initializes a REST call to get user data from the server. .then(...) is a callback that runs after data is returned. However, this getUser() function, as written, always returns an empty object, because it returns before the callback is triggered. How might I go about writing this function so that it returns the retrieved object?
(p.s. I know that this question is academic with regard to angular, since it handles promise resolutions transparently. I'm new to JS in general, and this is a general JS question).
Since server call is asynchronous, you should provide callback.
You can use promise or callback
Using Callback
function getUser(username, callback){
Restangular.one('users', username).get().then(function(result){
callback(result);
});
}
call: getUser('username', function(result){ /*do stuff here */ });
Using Promise
function getUser(username){
var callback;
var promise = {then: function(cb){
callback = cb;
}
};
Restangular.one('users', username).get().then(function(result){
callback(result);
});
return promise;
}
call: getUser('username').then(function(result){ /*do stuff here */ });)
Just try with:
function getUser(username, callback){
Restangular.one('users', username).get().then(callback);
}
getUser('hsz', function(result){
console.log(result);
});
The rest call is probably an async call. If you have control over the API, you can make a synchronous request which will then wait for it to return. Something like this:
function getUser(username){
var toReturn = { };
return Restangular.one('users', username).get().then(function(result){
return result;
});
}
It depends on how then is handled too. I'm assuming here that then() will return the result as well.
However, the best way in this scneario is to use a callback:
function getUser(username, callback) {
Restangular.one('users', username).get().then(callback);
}
Yes, that won't work because the problem is with your function. Every AJAX call is executed asynchronously, thus like the result.
If you have made an AJAX call like that, it will have to ask the browser to load that request, process the response and then execute the (function(result) { }) that you put as the last argument with the result.
So, you must change your function to have a callback too, like:
function getUser(username, onResultHandler){
Restangular.one('users', username).get().then(onResultHandler);
}
Then you can use it like this:
getUser('Daniel', function(user) { updateSomethingWithMyUser(user); });
Did you get it?
The simplest way, is to not overwrite the object you just created, because objects are passed around by reference.
For example:
var a = function() {
var b = {};
setTimeout(function() { b.a = 'hi'; }, 100);
return b;
}
b = a();
console.log(b); // Object {}
setTimeout(function() { console.log(b) }, 100); // Object {a: "hi"}
Because we simply set a property of the object, we are setting a property on the SAME object that got returned. When you do something like:
toReturn = result;
like in your function, you aren't changing the thing toReturn referenced, you are changing what toReturn references to (it used to reference to {}, now it references whatever result it).
So, in your case:
function getUser(username){
var toReturn = { };
Restangular.one('users', username).get().then(function(result){
toReturn.result = result;
});
return toReturn;
}
As soon as you get the result, toReturn.result will have it.
How might I go about writing this function so that it returns the retrieved object?
You can't, and you shouldn't. Restangular makes the call async so that your application can carry on running while waiting for a response.
If you want to make it look synchronous, I suggest the following approach (here's where its different from other answers):
function getUser(username){
return Restangular.one('users', username).get();
}
/* Usage */
getUser('username')
.then(function(result) {
/* do something with result */
});
From what I understand, the future style to write async code in JS is to use generators instead of callbacks. At least, or esp. in the V8 / Nodejs community. Is that right? (But that might be debatable and is not my main question here.)
To write async code with generators, I have found a few libraries:
gen-run (What I'm currently using.)
co
task.js
Galaxy
They all look kind of similar and I'm not that sure which of them to use (or if that even matters). (However, that might again be debatable and is also not my main question here -- but I still would be very happy about any advice.)
(I'm anyway only using pure V8 - if that matters. I'm not using Nodejs but I use pure V8 in my custom C++ app. However, I already have a few node-style elements in my code, including my custom require().)
Now I have some function X written in callback-style, which itself calls other async functions with callback arguments, e.g.:
function X(v, callback) {
return Y(onGotY);
function onGotY(err, res) {
if(err) return callback(err);
return Z(onGotZ);
}
function onGotZ(err, res, resExtended) {
if(err) return callback(err);
return callback(null, v + res + resExtended);
}
}
And I want to turn X into a generator, e.g. I guess function* X(v) { ... }. How would that look like?
I went with my very simple own lib which works quite well for my small V8 environment and also makes it easy to debug because the JS callstack stays intact. To make it work with Nodejs or on the web, it would need some modifications, though.
Rationales here:
For debugging, we don't really want async code - we want to have nice understandable call stacks in debuggers, esp. in the node-inspector debugger.
Also note that so far, all async code is completely artificial and we execute everything completely in sync, somewhat emulated via V8 Microtasks.
Callback-style async code is already hard to understand in call stacks.
Generator-style async code looses the call stack information completely in conventional debuggers - that includes the current Chrome Beta Developer Tools V8 debugger used with node-inspector. That is very much the nature of generators (coroutines in general). Later versions of the debugger might handle that, but that is not the case today. We even need some special C++ code to get the info. Example code can be found here:
https://github.com/bjouhier/galaxy-stack/blob/master/src/galaxy-stack.cc
So if we want to have useful debuggers, today, we cannot use generators -- at least not as it is usually done.
We still want to use generator-style async code because it makes the code much more readable, compared to callback-style code.
We introduce a new function async to overcome this. Imagine the following callback-style async code:
function doSthX(a, b, callback) { ... }
function doSthY(c, callback) {
doSthX(c/2, 42, function(err, res) {
if(err) return callback(err);
callback(null, c + res);
})
}
Now, the same code with the async function and generator-style code:
function* doSthX(a, b) { ... }
function* doSthY(c) {
var res = yield async(doSthX(c/2, 42));
return c + res;
}
We can provide two versions of async(iter):
Run the iterator iter on top of the stack. That will keep a sane call stack and everything is run serially.
Yield the iterator down to some lower handler and make it really async.
Note that there are a few notable libraries which can be used for the second approach:
https://github.com/visionmedia/co
http://taskjs.org/
https://github.com/creationix/gen-run
https://github.com/bjouhier/galaxy
For now, we just implement the first approach - to make debugging easier.
If we once want to have both, we can introduce a debug flag to switch via both implementations.
global.async = async;
function async(iter) {
// must be an iterator
assert(iter.next);
var gotValue;
var sendValue;
while(true) {
var next = iter.next(sendValue);
gotValue = next.value;
if(!next.done) {
// We expect gotValue as a value returned from this function `async`.
assert(gotValue.getResult);
var res = gotValue.getResult();
sendValue = res;
}
if(next.done) break;
}
return {
getResult: function() {
return gotValue;
}
};
}
// Like `async`, but wraps a callback-style function.
global.async_call_cb = async_call_cb;
function async_call_cb(f, thisArg /* , ... */) {
assert(f.apply && f.call);
var args = Array.prototype.slice.call(arguments, 2);
return async((function*() {
var gotCalled = false;
var res;
// This expects that the callback is run on top of the stack.
// We will get this if we always use the wrapped enqueueMicrotask().
// If we have to force this somehow else at some point, we could
// call runMicrotasks() here - or some other waiter function,
// to wait for our callback.
args.push(callback);
f.apply(thisArg, args);
function callback(err, _res) {
assert(!gotCalled);
if(err) throw err;
gotCalled = true;
res = _res;
}
assert(gotCalled);
return res;
})());
}
// get the result synchronously from async
global.sync_from_async = sync_from_async;
function sync_from_async(s) {
assert(s.getResult); // see async()
return s.getResult();
}
// creates a node.js callback-style function from async
global.callback_from_async = callback_from_async;
function callback_from_async(s) {
return function(callback) {
var res;
try { res = sync_from_async(s); }
catch(err) {
return callback(err);
}
return callback(null, res);
};
}
global.sync_get = sync_get;
function sync_get(iter) {
return sync_from_async(async(iter));
}
// this is like in gen-run.
// it's supposed to run the main-function which is expected to be a generator.
// f must be a generator
// returns the result.
global.run = run;
function run(f) {
return sync_get(f());
}
I assume that by "turning X into a generator" you mean "turning X into something you can yield", because that's how these libs work.
If you are using co (which I recommend), you need to make your function return thunks, that is a function, which accepts only a callback. Quite simple:
function coX (v) {
return function (cb) {
X(v, cb);
}
}
And then just:
co(function * () {
yield coX('v');
})();
I want to understand one thing about async module in node.js.
I have created a function that map an object from a form to a model object and return this object.
This object is a video with an array of tags.
My question is where can I return the video ? I know normally it is inside the async callback function but if I do that, the object returned is undefined.
Whereas If i return the video object at the end of the whole function, it works but it's not safe as I'm not sure, my async is finished...
By the way, I don't understand the callback function passed in argument to async.each and
called after video.products.push(tag); . What does this function do?
Regards
in my mapping.js :
exports.video = function(object) {
var video = new Video();
video.name = object.name;
video.products = [];
async.each(object.tags, function(tago, callback) {
tag = {
"name" : tago.name
}
video.products.push(tag);
callback();
} ,
function(err) {
if( err ) {
console.log('Error' + error);
throw err;
}
logger.debug("into async" + video);
}
);
logger.debug("end function " );
**//return video;**
}
in my video.js :
var video = mapping.video(object);
logger.debug(video); // return undefined
The simple answer is that you can't - at least not via easy or obvious approach. As its name suggests, async is a library for queuing up asynchronous function calls into the event loop. So your exports.video function simply kicks off a bunch of asynchronous functions, which execute one after the other on an unpredictable time-frame, and then returns immediately. No matter where you try to return your video object within the scope of your function calls which are instantiated by async, the exports.video function will already have returned.
In this case it doesn't really seem like you need asynchronous function calls for what you're doing. I'd suggest that you replace your use of async with something like Underscore's each method, which executes synchronously, instead.
http://documentcloud.github.io/underscore/#each
You'd need to define a callback for your exports.video function e.g..
exports.video = function(object, callback) {
// video code (snip)...
async.each(object.tags,
function eachTag(tag, done) {
// code run for each tag object (snip)...
done();
},
function finished(err) {
// code run at the end (snip)...
callback(thingThatsReturned);
});
};
...and call it like this:
var videoUtils = require('videoUtils');
var tags = getTags();
videoUtils.video({ tags: tags }, function(thingThatsReturned) {
// do something with 'thingThatsReturned'
});
By the way, I don't understand the callback function passed in
argument to async.each and called after video.products.push(tag); .
What does this function do?
The async.each function will call the 'eachTag' function above (2nd argument) for each item in your array. But because it's done asynchronously, and you might do something else async in the function (hit a database/api etc.), it needs to know when that function for that particular array item has finished. Calling done() tells async.each that the function has finished processing. Once all the functions are finished processing (they've all called done()), async.each will run the 'finished' function above (3rd argument).
This is pretty standard async stuff for Node.js, but it can be tricky to get ones head around it at first. Hang in there :-)
Edit: It looks like your code isn't doing anything asynchronous. If it was, then the above code would be the way to do it, otherwise the following code would work better:
exports.video = function(object) {
// video code (snip)...
if (Array.isArray(object.tags)) {
object.tags.forEach(function eachTag(tag) {
// code run for each tag object (snip)...
});
}
return thingThatsReturned;
};
...and call it...
var videoUtils = require('videoUtils');
var tags = getTags();
var thingThatsReturned = videoUtils.video({ tags: tags });
For error reporting, I would like to insert a try-catch wrapper around the code of every function I have.
So basically I want to replace
function foo(arg){
bar();
}
...with...
function foo(arg){
try {
bar()
}
catch(e){
customErrorHandler(e)
}
}
Is there a way to apply this generic try-catch thing to all functions without manually editing all of them? For example by modifying the prototype of the Function object?
EDIT
Why I want to try-catch all my functions:
I am building an HTML5 app that I'm publishing on iOS and Android. I can tell from my current rudimentary javascript error reporting that even though the app runs nicely on my own device, errors do occur on some other devices.
My objective is twofold: whenever a javascript error occurs on someone's device...
I want to notify the user that the app may not function perfectly
I want to know roughly where the error occurred, so I know where to look for the problem
This isn't simple since there is no way to find all JavaScript function defined everywhere. For example, any such approach would probably miss callback functions which are defined at runtime.
You also probably don't want to wrap all functions because that would include browser functions and functions from JavaScript libraries that you certainly don't want to wrap.
A much better approach is probably to define a function which wraps another function:
var tcWrapper = function(f) {
return function() {
try {
f.apply(this, arguments);
} catch(e) {
customErrorHandler(e)
}
}
}
Now you can use this function to decorate anything that you want. Wrapping will become more simple if you use name spaces:
var NS = { f: function() { } }
Just put all functions to wrap in a special namespace and then iterate over the namespace:
$.each( NS, function(i,n) {
var p = NS[i];
if( typeof p === 'function' ) {
NS[i] = tcWrapper(p);
}
} );
I don't have enough reputation to comment on the accepted answer.
I added a return before the f.apply to pass up the return value as well.
var tcWrapper = function(f) {
return function() {
try {
return f.apply(this, arguments);
} catch(e) {
customErrorHandler(e)
}
}
}
The given answers already work well, just wanted to share a new one using closures.
Define wrapper
const tryCatchWrapper = (executable) => async (...args) => {
try {
const result = await executable(...args);
return result;
} catch (error) {
// use any custom handler here
error.message = `[${executable.name}] - ${error.message}`;
error.data = {...error.data, input_args: args}
throw error;
}
}
Your function without a try-catch wrapper
const myFunction = async (x, y) => {
const sum = x + y;
if (sum > 10) throw new Error(`sum > 10 custom error`)
return sum;
}
How to use it
try {
const wrapperFunction = trycatchWrapper3(myFunction2);
const output = await wrapperFunction(2, 93)
console.log(output)
} catch (error) {
console.error(error)
}
END
Okay, I seem to have found it here: http://www.nczonline.net/blog/2009/04/28/javascript-error-handling-anti-pattern/
Basically, all functions are replaced by a try-catch wrapper with the original function in the try part.
I needed to go fortify some code, so I wrote a function called fortify and put it in an NPM module. It's a work in progress, but it should help.
https://github.com/infinitered/over-armour
Bonus: it works with async functions. Feedback welcome
I wonder (this is pure speculation, so not sure if this would work) you could do something like this:
function callTryCatch(functionSignature) {
try {
eval(functionSignature);
} catch (e) {
customErrorHandler(e);
}
}
function entryPoint() {
callTryCatch(function() {
// do function logic
});
}
Again, this is pure speculation and I haven't tested but if it's even possible I think the key lies in the eval statement.