Need help understanding parameters [duplicate] - javascript

I have trouble understanding how callbacks in JavaScript get their arguments. Or in other words: how to implement a higher-order function so its callback accepts for instance a standard err and data arguments.
Like in this article on asynchronous JavaScript in the example of a callback used in a usual way (and I know it's usual because I see exactly this pattern used in Node.js moongose (i.e. for creating data in db)):
function getData(options, callback) {
$.get("example.php", options, function(response) {
callback(null, JSON.parse(response));
}, function() {
callback(new Error("AJAX request failed!"));
});
}
// usage
getData({name: "John"}, function(err, data) {
if(err) {
console.log("Error! " + err.toString())
} else {
console.log(data);
}
});
how exactly the callback gets arguments err & data based on how getData() function is declared above?

Arguments are passed to a function when that function is called.
function foo(arg) {
console.log(arg);
}
foo("This is the value");
This is still true when it is a callback function.
function foo(arg) {
console.log(arg);
}
function bar(callback) {
callback("This is the value");
}
bar(foo);
And it is still true when the callback function is called by code written by someone else that exists in a library you aren't examining the source code of.

Related

Using callbacks appropriate as continuations in javascript

I'm familiar with callbacks and i know what synchronicity is, but there is still something I'm missing when it comes to continuation passing style. I've got this simple code example where I can't tell how to transform it to asynchronous code based on callbacks in continuation passing style:
function performOrder() {
var available, placedOrder;
available = checkCountOnServer(order.item, order.count);
if (!available) {
showNotAvailableMessage(order);
return;
}
placedOrder = checkPayment(order.item, order.count, order.paymentMethod);
if (askUserForConfirmationWithDialog(placedOrder)) {
return confirmOrder(placedOrder);
}
}
My approach to this was:
function performOrder() {
checkCountOnServerC(order.item, order.count, showNotAvailableMessage(order));
return checkPaymentC(order.item, order.count, askUserConfirmationWithDialogC(placedOrder, confirmOrder(placedOrder));
}
All Methods appended with C can be assumed to be modified to accept a callback as continuation.
My Questions are: Are both snippets equivalent and confirms the second one to the continuation passing style?
Thank you very much in advance!
Your code would execute checkCountOnServerC and checkPaymentC in parallel regardless of the status of available. Therefore they are not equivalent.
The correct transformation would depend on the style you want to adopt: node.js standard callback style, Promises, successCallback/errorCallback etc. Assuming you want to use node.js standard callback style:
function performOrderC(callback){
checkCountOnServerC(order.item, order.count, function(err, available){
if (! available ) {
showNotAvailableMessage(order));
callback(new Error('Not available'));
return;
}
checkPaymentC(order.item, order.count, function(err, placedOrder){
askUserConfirmationWithDialogC(placedOrder, function(){
callback(null, confirmOrder(placedOrder)); // this is how you "return" results
});
});
});
}
Node.js standard callback style uses the first argument of callbacks to pass errors up the stack. But before node.js this was not universally adopted by asynchronous functions.
If the above appears a bit dense (sometimes called callback-hell) you can always refactor it to not use anonymous functions:
function checkPaymentHandler (callback) {
return function (err, placedOrder){
askUserConfirmationWithDialogC(placedOrder, function(){
callback(null, confirmOrder(placedOrder)); // this is how you "return" results
});
});
}
function checkCountHandler (callback) {
return function (err, available) {
if (! available ) {
showNotAvailableMessage(order));
callback(new Error('Not available'));
return;
}
checkPaymentC(order.item, order.count, checkPaymentHandler(callback));
}
}
function performOrderC(callback){
checkCountOnServerC(order.item, order.count, checkCountHandler(callback));
}

How do I use a callback in a nested function in Node?

I'm receiving a "TypeError: callback is not a function" which leads me to believe I am misunderstanding how to use callbacks in a nested function.
Function:
function getAudioInfo(filePath, callback) {
ffprobe(filePath, { path: ffprobeStatic.path }, function (err, info) {
console.log("ffprobe output: " + JSON.stringify(info));
if (err) {
console.log("getAudioInfo error: " + err);
callback(err, null);
} else {
callback(null, info);
}
});
}
Call:
function checkAudioInfo(metadata_json, callback) {
var filePath = metadata_json['current_path'];
getAudioInfo(filePath, function(err, info) {
if (err) {
callback(err);
}
//operations on info
callback(null, metadata_json);
});//end getAudioInfo
}//end checkAudioInfo
Is this an improper use of callbacks?
Edit:
Error was found in passing to the function wrapping checkAudioInfo (another callback error). I will make edits and post the correct code shortly. All your questions helped me figure out the answer. Thanks!
Your first block of code accepts a callback. The second argument should be a function. This function will be called when the asynchronous code is done.
Your second block of code calls the function in the first. The second argument you are passing is a function. So far, so good.
Inside that function, you try to call callback. This fails because there is no variable with that name in scope.
At this point, it is very unclear what you are trying to do. The function you are passing is the callback. You are supposed to use it to do something useful with the data it is passed by the code from the first code block.
Now, you could get a reference to the callback function by using a named function expression:
getAudioInfo(filePath, function callback (err, info) {
if (err) {
callback(err);
}
//operations on info
callback(null, metadata_json);
});//end getAudioInfo
… but then you are just calling it recursively and infinitely, which is not useful.
re Edit:
You have now added a second variable called callback:
function checkAudioInfo(metadata_json, callback) {
This makes more sense.
If that callback is undefined, then that is because you aren't passing it a value when you call checkAudioInfo. You haven't included that code.
The function itself function(err, info) is the callback which is called inside of getAudioInfo!
What is metadata_json? Do you mean info?

numerous nested functions in javascript

I've been reading about async functions in JavaScript and found out that I don't quite understand the following piece of code that comes from here.
Here it is:
doSomething(function(result) {
doSomethingElse(result, function(newResult) {
doThirdThing(newResult, function(finalResult) {
console.log('Got the final result: ' + finalResult);
}, failureCallback);
}, failureCallback);
}, failureCallback);
What I don't understand is where all these results come from.
They are callbacks. A callback is just simply a function which is passed as an argument to another function and is used to do something with the result of some operation done by the function which receives the callback as an argument. You can write your own. A simple example:
function callMe(callback) {
let addition = 2 + 2;
callback(addition);
}
callMe(function(result) {
console.log(result);
});
callMe calls its callback function with the result of 2 + 2. You then receive that result inside the callback function when you use callMe, and you can then write your own custom code to do whatever you want with it.
The beauty of JavaScript is that you already have all you need to test it.
The code you posted references 4 functions (don't forget the failure callback):
doSomething(function(result) {
doSomethingElse(result, function(newResult) {
doThirdThing(newResult, function(finalResult) {
console.log('Got the final result: ' + finalResult);
}, failureCallback);
}, failureCallback);
}, failureCallback);
Those functions are not written. So let's write them:
var failureCallback = function() {
console.log('something went wrong');
}
var doSomething = function(callback) {
window.setTimeout(function() {
var result = Date.now(); // Create some data that will change every time the function is invoked
callback(result);
}, 500);
}
var doSomethingElse = function(res, callback) {
window.setTimeout(function() {
var result = [res]; // all this function really does is put the first argument in an array
callback(result);
}, 500);
}
function doThirdThing(res, callback) {
window.setTimeout(function() {
res.push(Math.PI); // res is supposed to be an array, so we can add stuff to it.
var result = res;
callback(result); // here we could have used res as a value, but I kept it consistent
}, 500);
}
doSomething(function(result) {
doSomethingElse(result, function(newResult) {
doThirdThing(newResult, function(finalResult) {
console.log('Got the final result: ', finalResult); // switched to a comma to display properly in the console
}, failureCallback);
}, failureCallback);
}, failureCallback);
To create some asynchronicity I used setTimeout so overall you have to wait 1.5 seconds.
The 3 functions that use a callback function as an argument, simply execute the function they were given. This is absolutely standard in JavaScript where functions are first class objects: you can pass them around as arguments like any other value type.
Javascript is a single threaded language, callbacks are used as a way to control the flow of execution when a asynchronous block of code ends in a non-blocking way. A callback is normally just another function (function B) that is passed into the asynchronous function (function A) to run when function A completes. I.E
doSomething(func) {
// do async code.
// call func
// func()
}
you haven't posted the inner blocks of those functions but i think we can all safely assume "result" is the response from the server passed back into the callback function I.E
doSomething(callback) {
//fetch or ajax or whatever to server store response.
//pass response BACK to callback function
callback(response)
}

Javascript: pass parameters to callback function

I want to call a function on the returned data from this database query, as in the snippet below.
function connectDB(query, data, callback) {
pg.connect(process.env.DATABASE_URL, function (err, client) {
if (err) {
console.log(err);
} else {
client
.query(query, data, function (err, result) {
callback(result.rows);
});
}
}
}
function foo(data) {
connectDB("SELECT * FROM mytable WHERE id=$1", someID, callbackfn(data));
}
I don't know how to write callbackfn so that I can use both data from the original function and rows from the db result.
function callbackfn(data) {
return function(rows) {
// Do something with rows and data
}
}
You don't accept any params with the callback function. How about:
function callback(rows) {
/* not sure what your intention was here? nested functions? */
return function () {
return function () {
// Do something with rows
}
}
}
And to be clear, can you post where you call the connectDB function? As callback is name of the variable after it is passed to connectDB.
Why are you defining callback function? Please elaborate on this. Also, try calling connectDB like this:
connectDB(query, data, function(rows) {
// Do something with rows
});
Read this answer on callbacks.
You have an incredible level of nested functions. Moreover, you are defining callback as parameter, but it won't take the callback function you defined, if you are not calling the base function passing again "callback" as argument.
If you want to pass always the same callback, it doesn't make sense that you provide it as argument, you can directly call "callback" inside your "connectDB" function. Moreover your callback returns a function, so it should be called again using again ().
Then your main callback function needs to accept rows as parameter from outside.
I kept your code using the callback parameter because I "hope" that the same name was just an example to explain that you want to provide every time a function in order to manipulate as you want the rows.
You code should look like this:
function connectDB(query, data, callback) {
pg.connect(process.env.DATABASE_URL, function (err, client) {
if (err) {
console.log(err);
} else {
client
.query(query, data, function (err, result) {
// this returns a function so it needs to be called again
callback(result.rows)();
});
}
}
}
// third inner function was useless
function callback(rows) {
return function () {
// Do something with rows
}
}
// the third parameter HAS TO BE callback, otherwise you will not pass the function you defined.
connectDB(query, data, callback);

Trying to decode the word "callback" in this node.js code

I am new to node.js and came across this bit of code and am trying to understand what the word "callback" is doing. I mean I know what a callback is, but why are they actually using the word "callback" below and what is it doing. Really appreciate your help.
io.sockets.on('connection', function(socket) {
socket.on('nickname', function(data, callback) {
if (nicknames.indexOf(data) != -1) {
callback(false);
} else {
callback(true);
nicknames.push(data);
socket.nickname = data;
console.log('Nicknames are ' + nicknames);
}
});
});
It's a variable name.
It's defined in the function expression as an argument: function (data, callback) {.
The expectation is that the value passed to it will be a function (hence the function being called here: callback(false);).
For a simple example that doesn't depend on any library code you can't see:
function doSomething(callback) {
alert("doing something");
callback(1);
}
function myCallback(value) {
alert("myCallback called with the argument: " + value);
}
doSomething(myCallback);
But function (data, bob) is the callback function. Why include "callback" (or bob) within the callback. Does that make sense?
You have multiple callback functions.
One callback function is passed another function as an argument which it, in turn, calls.
Node.js uses asynchronous callback functions instead of blocking the caller and performing the operation synchronously. callback is simply the very common name given to the variable that holds the callback function. I usually name the variable done in my own code simply because it is shorter.
In Node.js, callback is the de-facto standard name for callback functions. You could easily call it bob, and it would have the same effect:
io.sockets.on('connection', function(socket) {
socket.on('nickname', function(data, bob) {
if (nicknames.indexOf(data) != -1) {
bob(false);
} else {
bob(true);
nicknames.push(data);
socket.nickname = data;
console.log('Nicknames are ' + nicknames);
}
});
});
As to what it's doing, think of it as an anonymous function that notifies the caller (like a parent function) that the called function is done. A simpler example would be:
Function A calls function B (which takes a long time to run). When B is done, it needs to tell A that it's done:
function a() {
b(someParameter, function(err, data) {
// function(err, data) is the anonymous function we pass as a parameter to b()
});
}
function b(someParemeter, callback) {
// do something that takes a while
// 'callback' is the variable name for the anonymous function that was passed
// We execute it using ():
callback(err, data);
}
Assuming that this is socket.io, that callback is used to respond to a client when the 'nickname' event is triggered.
From their documentation
Sending and getting data (acknowledgements)
Sometimes, you might want to get a callback when the client confirmed
the message reception.
To do this, simply pass a function as the last parameter of .send or
.emit. What’s more, when you use .emit, the acknowledgement is done by
you, which means you can also pass data along:
Server (app.js)
var io = require('socket.io')(80);
io.on('connection', function (socket) {
socket.on('ferret', function (name, fn) {
fn('woot');
});
});
Client (index.html)
<script>
var socket = io(); // TIP: io() with no args does auto-discovery
socket.on('connect', function () { // TIP: you can avoid listening on `connect` and listen on events directly too!
socket.emit('ferret', 'tobi', function (data) {
console.log(data); // data will be 'woot'
});
});
</script>

Categories

Resources