Trying to replicate callBack hell - javascript

I have been trying to learn about callBack hell, and was trying to replicate and then change it into promises. Here is my code, its saying on execution cb is not a function
What i am missing here.
var t = addTwo(function(a, b) {
console.log(a * b);
divideTwo(function() {
console.log("arshita");
})
})
function addTwo(cb) {
cb(3, 4);
}
function divideTwo(cb1) {
}
addTwo();

You have an error in your code
var t = addTwo(function(a, b) {
console.log(a * b);
divideTwo(function() {
console.log("arshita");
})
})
function addTwo(cb) {
cb(3, 4);
}
function divideTwo(cb1) {
}
addTwo((a, b) => a + b); // <----- Here you passed nothing, though `addTwo`
// expected a callback. I wrote an example callback that sums `a` and `b`
Update
If you want to see what callback hell looks like, then have a look at this (a simple, only 3-level callback hell):
function init(msg, cb) {
alert(msg)
cb()
}
function running(msg, cb) {
alert(msg)
cb()
}
function finish(msg) {
alert(msg)
}
// The below code may not be considered as "callback hell" yet, but add few more iterations and it definitely will become a hell
init('program started!', function() {
running('program is running', function() {
finish('program shut downs')
})
})

Related

There is any difference between callback function and calling a function inside another function?

Let's take this example:
function foo(callback){
callback();
baz();
}
function baz() {
console.log('Hello from baz');
}
foo(baz);
It looks like they are doing the same task. Or callback and calling a function inside another function are the same thing?
Except you aren't using the callback the way callbacks are supposed to be used. Callbacks are supposed to get the interim results from a previous function. Here's an example
function add (a, b) {
return a + b;
}
function subtract (a, b) {
return a - b;
}
This is the callback
function doLater (val) {
if (val > 0) {
console.log("positive");
} else if (val ==) {
console.log("zero");
} else console.log ("negative");
}
function doOp (a, b, mathOp, callback) {
var res = mathOp(a,b);
callback(res);
}
doOp (2,3, add, doLater);
vs.
doOp (2,3,subtract, doLater);
Basically, they are doing the same, but callbacks are very useful because you can call the same function with many different callbacks. That makes your foo function more reusable.
In your example, both approaches will do the same.
However, you can pass function as parameters, that are not in the functions scope.
E.g.
function foo(callbackFn){
callbackFn();
// function test is undefined here, since it was declared in another scope
}
function bar(){
// test is only available in bar's scope
function test(){
console.log("test");
}
foo(bar);
}

Passing a function and its parameters as a parameter to another

I've seen a few answers but its still a little unclear to me how to go about this.
I have a retry function, whose parameter of fn I'd like to call with the original parameters supplied to it:
function retry(fn, retries=3, err=null) {
if (!retries) {
return Promise.reject(err);
}
return fn().catch(err => {
return retry(fn, (retries - 1), err);
});
}
Is there a clean way to do this in JS?
In short, I'd like to do something like:
function a(b,c,d) { return Promise.resolve(b + c + d) }
retry(a, ...originalParams)
Besides what you've covered yourself, another way would be to wrap your function and it's arguments into a thunk. However, it's not exactly what you would like it to be.
function retry(fn, retries=3, err=null) {
if (!retries) {
return Promise.reject(err);
}
return fn().catch(err => {
return retry(fn, (retries - 1), err);
});
}
function toThunk(fn, ...args) {
// note that we return a new function which closes over
// the function and arguments here (e. g. creating closures)
return () => fn(...args);
}
function sumP(a, b, c) {
return Promise.resolve(a + b + c);
}
// ---
retry(toThunk(sumP, 1, 2, 3)).then(result => {
console.log(result);
});

Error callback is not a function in node.js

I'm quite new to JS and I don't really understand callbacks and I have looked for a fix for this error but I can't seem to find it.
When I execute the code I get this error : TypeError: callback is not a function -> callback(false);
function doesLobbyExist(a, callback) {
lobbyExists(a, function(random_data) {
callback(random_data);
});
}
function lobbyExists(a, callback) {
if(lobbies.length > 0){
lobbies.forEach(function(l) {
if(l.lobbyName == a){
console.log(a+" exists!");
callback(true);
}
});
}else{
callback(false);
}
}
And I call it like this:
doesLobbyExist(a.ln, function(result) {
console.log(result);
});
P.S. the code goes through console.log(a+" exists!");
I'm unable to reproduce what you're seeing. Running your code under a couple of different conditions, I got the following results:
> var lobbies = [{ lobbyName: 'foo' }];
> doesLobbyExist('foo', console.log)
foo exists!
true
> doesLobbyExist('bar', console.log)
...
> var lobbies = [{ lobbyName: 'foo' }, { lobbyName: 'bar' }, { lobbyName: 'foo' }];
> doesLobbyExist('bar', console.log)
bar exists!
true
> doesLobbyExist('foo', console.log)
foo exists!
true
foo exists!
true
...
> var lobbies = [];
> doesLobbyExist('foo', console.log)
false
but there a couple of problems in your code:
lobbyExists only gives a false response if there are no lobbies to check, it's possible for it to call the callback multiple times if there are multiple lobbies with the same name, and it doesn't return anything if a lobby isn't found.
there's no easy way to break out of forEach. since you only want to call your callback function once, you'll want to either return or break once a lobby has been found. switching over to a for i loop allows us to do either one.
comparison using == is what's known as loose or abstract equality, which may cause errors down the road - you can read up on the difference between loose (==) and strict (===) equality here.
if the lobbyExists function is only iterating through an array, then there's no need to treat it as asynchronous and use a callback. synchronous callbacks are a thing, and are perfectly fine to use, but it's something to be aware of as you continue to develop.
with all that being said, these are the changes that I would suggest:
function doesLobbyExist(a, callback) {
lobbyExists(a, function(random_data) {
//possibly do other things to random_data...
callback(random_data);
});
}
function lobbyExists(a, callback) {
for(var i = 0; i < lobbies.length; i++) {
var l = lobbies[i];
if(l.lobbyName === a) {
console.log(a + " exists!");
callback(true);
return;
}
}
callback(false);
}
It seems to me you're overcomplicating things, callbacks are simple to understand when you get the basic concept. I'll just try to leave a little primer on callback functions here and perhaps you can figure out where you went wrong in your own implementation. Consider the following code:
function lobbyExists(a, callback) {
if (a === 1) {
callback(true);
} else {
callback(false);
}
}
lobbyExists(1, function(response) {
console.log(response);
});
lobbyExists(0, function(response) {
console.log(response);
});
In this case, you are passing the entire function(response) { console.log(response); } function as a reference in the variable callback in lobbyExists. This means when executing lobbyExists, the variable callback now refers to that function. When you say callback(true) you are therefore calling function(response) { console.log(response); } where response is true.
I executed the code snippets and it worked fine for me.
Run the code below.
var lobbies = [{lobbyName:"a"}]
function doesLobbyExist(a, callback) {
lobbyExists(a, function(random_data) {
callback(random_data);
});
}
function lobbyExists(a, callback) {
if(lobbies.length > 0){
var bool = false
lobbies.forEach(function(l) {
if(l.lobbyName == a){
bool = true;
}
});
callback(bool);
return false;
}
callback(false);
}
doesLobbyExist("a", function(result) {
console.log(result);
});
However I changed lobbyExists function a little since callback would not call if there was no match found.
If you couldn't make it work try changing the variable name of callbacks in each function
Ex : Instead of "callback" use "cb"
More about callbacks
Similar question on stack

What would the function definition look like if it uses another function inside - JavaScript

I have found this code on SO :
function dothings(things, ondone){
function go(i){
if (i >= things.length) {
ondone();
} else {
dothing(things[i], function(result){
return go(i+1);
});
}
}
go(0);
}
I couldn't figure out how I should define dothing function. Should it be like this :
function dothing(elem)
{
//do things with elem
}
Or should I somehow indicate the function(result), if yes how should I do that? Thanks in advance.
The dothing is an asynchronous function here.
In asynchronous function signature, a callback is one of the params.
Also in order to return a value from a async function, the callback needs to be called with the value to be returned.
A return statement does not make sense in async function.
The definition can look like:
function dothing(elem, callback){
// Your logic to process elem
// var result = some_custom_logic(elem);
callback(result);
}
do it like this,
function dothing(elem, cb)
{
//do things with elem
// return the result
cb(...somedata)
}
You can define dothing like this
function dothing(elem, callback){
//result = do stuff with elem
callback(result);
}
It looks a bit overcomplicated, because it calls the function over and over again and does not work for the elements of things and and in the reverse order for calling ondone function.
function dothings(things, ondone) {
function go(i) {
if (i < things.length) {
console.log(i, things[i]);
go(i + 1);
ondone(i);
}
}
go(0);
}
dothings([1, 2, 3, 4], function (v) { console.log(v, 'done'); })
.as-console-wrapper { max-height: 100% !important; top: 0; }

Anonymous callback functions

So, I understand callback functions to a degree. For instance, I completely understand this:
function finalGuy(x) {
alert("Final Number: " + x);
}
function secondGuy(x, callback) {
x = x - Math.sqrt(x);
callback(x);
}
function firstGuy(callback) {
var x = parseInt(prompt("Enter a number"));
x *= x;
secondGuy(x, callback);
}
firstGuy(finalGuy);
However, when faced with something like this I can't seem to grasp it.
a(function () {
b(function () {
c()
})
});
Can someone please translate the first sequence of callbacks into a working example like the second one? Specifically, passing one result to the next callback similarly to how I did it in the first example.
These two produce the same result
1.
function acceptCallback(callback) {
callback();
}
function callback() {
console.log('callback invoked');
}
acceptCallback(callback); // => 'callback invoked'
2.
function acceptCallback(callback) {
callback();
}
acceptCallback(function() {
console.log('callback invoked');
});
In the first example you pass a function declaration, in the second example you pass an anonymous function
3. Performing operations in the scope of a callback to be passed to another callback, aka "callback hell"
Nothing special here, it's the same syntax as the first two examples. This is difficult to read for anyone.
function first(callback) {
callback('from first');
}
function second(callback) {
callback('from second');
}
function third(callback) {
callback('from third');
}
function fourth(n, callback) {
callback(n * 10);
}
first(function(fromFirst) {
var a = 5;
console.log(fromFirst); // 'from first'
second(function(fromSecond) {
console.log(fromSecond); // 'from second'
third(function(fromThird) {
console.log(fromThird); // 'from third'
var b = a + 5; // 10
fourth(b, function(fromFouth) {
console.log(a, b, fromFourth); // 5, 10, 100
})
});
});
});

Categories

Resources