I'm a noob in coding. I'm really sorry about that. I have this code here....
function fn1(){
setTimeout(function(){console.log("fn1")},3000)
}
function fn2(){
console.log("fn2")
}
function fn3(callback, callback2){
if(callback){
console.log("It works!")
} else {
callback2
}
}
fn3(fn1(),fn2())
The objective here is to call Function3(fn3) console.log ("It works") only after Function1(fn1) runs ok. If Function1 fails, it should return Function2.
The output that I'm getting is:
fn2
fn1
I know it is extremely wrong but I don't know WHAT is wrong.
I know that there are other stuff (that I still don't know - like promises, async, await and stuff) but I wanna learn this method first.
Could you guys help me?
Yes, you are right. This is a huge nonsense.
Correct me if I'm wrong: you want the console to log "It works!" after the timeout set in the fn1. Then you'll need the fn1 to tell somehow that it finished it's execution so it can run the console.log. If you want to use the callback approach, then the fn1 could be something like:
function fn1(callback, errorCallback) {
setTimeout(function() {
try {
callback();
} catch (error) {
errorCallback();
}
}, 3000);
}
And the fn3 could go like this:
function fn3() {
fn1(function() { console.log('It works!'); }, fn2);
}
You can call fn3 just with fn3().
To be honest, as simple as these functions are, there's no way the fn2 is called as there are no errors in the code and no human interaction. Well, maybe if there's no standard output available to do the console.log, but I don't know if that's even possible.
As you can see, in the fn3 we are passing two functions as parameters to fn1. The first is an anonymous function that shows the text in the output. The second function is the fn2, that should be run in case of error. No parenthesis here when passing them as parameters as we want to pass functions, not the result of calling them (which would be undefined in this example).
The fn1 receives those functions as parameters and runs them in different situations. The first, when the timeout has finished, and the second if there's any error when calling the callback.
You have to pass references on the functions as parameters of fn3 (you currently call them and pass their result).
Also, in the fn3, you need to call the function.
Your code fixed below (if I correctly understood what you were looking for):
function fn1(next) {
setTimeout(next, 3000);
}
function fn2() {
console.log("fn2")
}
function fn3(callback, callback2){
function itWorks() {
console.log('it works!');
}
try {
callback(itWorks);
}
catch (e) {
callback2();
}
}
fn3(fn1, fn2); // Will display "it works!" after 3 seconds
fn3(undefined, fn2); // Will display "fn2" because trying to call an undefined function
I understood that you want to call f3 after the f1 is called successfully and call the f2 when f1 fails? If yes then see this
function fn3(){
console.log("It Works!");
}
function fn2(){
console.log("fn2");
}
function fn1(){
const promisePass = new Promise((resolve, reject) => {
setTimeout(resolve, 100)}); //Emulate success
const promiseFail = new Promise((resolve, reject) => {
setTimeout(reject, 100);});//Emulate fail
promisePass.then(function(){
fn3();
}).catch(function(){
fn2();
});
promiseFail.then(function(){
fn3();
}).catch(function(){
fn2();
});
}
fn1(); //<<-- calling f1 now will pass and fail the setTimeout method and then
// fn2 and fn3 are called accordingly
Related
I need to understand how callback functions works.
I wrote this little script with 2 functions :
function fn1(callback) {
alert('fn1');
callback();
}
function fn2() {
alert('fn2');
}
fn1(fn2); //display 'fn1' then 'fn2'
Now, I want to update my script with a "fn3" function in order to display 'fn1' then 'fn2' then 'fn3'. I tried this :
function fn1(callback) {
alert('fn1');
callback();
}
function fn2(callback) {
alert('fn2');
callback();
}
function fn3() {
alert('fn3');
}
fn1(fn2(fn3));
but it dispay 'fn2', then 'fn3', then 'fn1', then log an error ("callback is not a function").
Any idea ? what's wrong ?
Thanks in advance, Florent.
In order to execute f1 then f2 then f3 you need to create a callback function in order to make sure a function will be executed in steps.
wrong:
fn1(fn2(fn3))) // this first call f2 with f3 as parameter then calls f1 with its result
right:
fn1(function () { // call f1
fn2(function () { // then call f2 after f1
fn3(); // then call f3 after f2
})
})
This sounds more like you're looking for promises
function fn1(){
return new Promise(resolve => {
alert("fn1");
resolve()
});
}
function fn2(){
return new Promise(resolve => {
alert("fn2");
resolve()
});
}
function fn3(){
return new Promise(resolve => {
alert("fn3");
resolve()
});
}
fn1().then(fn2).then(fn3);
fn3
You take the value fn3 which is a function.
fn2(fn3)
You pass that value as the argument to fn2, another function, which you call.
function fn2(callback) { alert('fn2'); callback(); }
You alert, then you call the argument (the function you got from fn3) as a function (I'll skip over the details of what it does) and then return undefined (since you have no return statement).
fn1(fn2(fn3));
Since fn2(fn3) returns undefined this is the same as fn1(undefined).
function fn1(callback) { alert('fn1'); callback(); }
You alert, then try to call undefined as a function, which it isn't, so it errors.
How to call 3 or 4 callback functions
Probably… rewrite the functions so they make use of Promises instead of plain old callbacks.
But there is no point in using callbacks for your example at all, and the best solution to a real problem will depend on what that problem is.
fn1(fn2(fn3))
Here we have a call to function fn1 with 1 argument which is return value of function fn2. This statement is evaluated so that fn2 is first called with its parameter fn3 and then the return value is passed to fn1. fn2 calls its parameter. This is why you get "unexpected" order of alerts.
fn2 does not return anything so that is why you get error from fn1.
I'm working on a way to chain a set of 3 ajax calls per variable against an array of data with some delay in between.
Taking into account this answer.
I'm trying to update the code to achieve the following:
Add a delay in the b() and c() function
Pass a variable from a() to b() and from b() to c()
Is there a way I can pass a variable a() would generate to b() without using global variables? If not that's fine, I'd just like to know.
And how exactly can I get b() to be delayed for several seconds before processing c()? I would assume adding in a setTimeout would work as it's waiting for the promise before it starts c(), but this is not the case.
jsfiddle
function a(user, pass) {
return $.post('/echo/json/', {}, function(re){
console.log(1);
});
}
function b() {
setTimeout(function() {
return $.post('/echo/json/', {}, function(re){
console.log(2);
});
}, 3000);
}
function c() {
console.log(3);
}
var data = [{u: 'au', p: 'ap'}, {u: 'bu', p: 'bp'}];
var counter = 0;
function main() {
if(counter < data.length) {
$.when(a(data[counter].u, data[counter].p).then(b).then(c)).done(function(){
counter++;
main();
})
}
}
main();
To ensure that c() isn't executed until after the timeout code has been called, create your own promise and return it from the b() function. You should wrap the setTimeout function in this promise, and call the resolve(res) method to notify the .then() functions watching the promise, passing an object representing the data or body of the response.
function b(dataFromA) {
return new Promise((resolve, reject) => {
setTimeout(function() {
return $.post('/echo/json/', {}, res => {
let dataToB = res;
console.log(2);
resolve(dataToB);
});
}, 3000);
});
}
Note that b() now accepts data that can be passed from the response of the a() promise. You can manipulate this data inside the b(res) function or in the promiseFromA.then(res => { // ... Your promise callback code }); before calling b(res).
setTimeout as used in function b is not a promise. i will find some docs to site and post shortly but here is what i see.
to use a promise you need to call a promise method, setTimeout is not a promise. it is only a delay. it has to do with the event loop in javascript or in the javascript runtime to be more correct. there is some good stuff over here --> https://github.com/getify/You-Dont-Know-JS/tree/master/async%20%26%20performance
also .then only works to resolve a promise
getify really breaks it down but i would start with the javascript event loop
Executing the below using node - 6.0.
function A(callback) {
console.log('A');
callback();
}
function B() {
console.log('B')
}
function C() {
console.log('C');
}
A(C);
B();
// Result is A,C,B i expected that A, B, C
But changing the above example to use process.nextTick() prints A, B, C
function A(callback) {
console.log('A');
process.nextTick(() => {
callback();
});
}
function B() {
console.log('B')
}
function C() {
console.log('C');
}
A(C);
B();
Is this what we call as zalgo ? Can anyone provide me a realtime example of this, which will cause major breakdown ?
No, neither of these is zalgo. Your first A function always calls its callback synchronously, and should be documented as such. Your second A function always calls its callback asynchronously, and should be documented as such. Nothing is wrong with that, we use thousands of these every day. The outputs A C B and A B C are deterministic.
Zalgo refers to the uncertainty whether a callback is asynchronous or not.
function A(callback) {
console.log('A');
if (Math.random() < 0.5) {
callback();
} else {
process.nextTick(callback);
}
}
The output of the invocation A(C); B(); would be totally unpredictable.
First let me explain how the code works - see the comments in the code that I added:
// first you define function A and nothing happens:
function A(callback) {
console.log('A');
callback();
}
// then you define function B and nothing happens:
function B() {
console.log('B')
}
// then you define function C and nothing happens:
function C() {
console.log('C');
}
// now you call function A with argument C:
A(C);
// when A runs it prints 'A' and calls C before it returns
// now the C runs, prints C and returns - back to A
// A now has nothing more to do and returns
// Now the execution continues and B can be run:
B();
// B runs and prints 'B'
This is exactly the same as it would be in any language like Java, C etc.
Now, the second example:
// first you define function A and nothing happens:
function A(callback) {
console.log('A');
process.nextTick(() => {
callback();
});
}
// then you define function B and nothing happens:
function B() {
console.log('B')
}
// then you define function C and nothing happens:
function C() {
console.log('C');
}
// Then you run A with C passed as an argument:
A(C);
// A prints 'A' and schedules running an anonymous function:
// () => { callback(); }
// on the next tick of the event loop, before I/O events are handled
// but after the current code stack is unrolled
// then it returns
// And then B is run:
B();
// B prints 'B' and returns
// Now nothing else is left to do so the next tick of the event loop starts
// There's one function to run, scheduled earlier so it runs.
// This function runs the `callback()` which was `C`
// so C starts, prints 'C' and returns
// The anonymous function has nothing else to do and returns
// There is no more things on the event loop so the program exits
Update
Thanks to Bergi for explaining what is Zalgo in his answer. Now I better understand your concerns.
Is this what we call as zalgo ? Can anyone provide me a realtime example of this, which will cause major breakdown ?
I've seen a lot of code like this:
function x(argument, callback) {
if (!argument) {
return callback(new Error('Bad argument'));
}
runSomeAsyncFunction(argument, (error, result) => {
if (error) {
return callback(new Error('Error in async function'));
}
callback({data: result});
});
}
Now, the callback can be either run immediately before x() returns if there are bad arguments, or after the x() returns otherwise. This code is very common. For testing the arguments one could argue that it should throw an exception but let's ignore that for a moment, there may be some better examples of operational errors that are known immediately - this is just a simple example.
Now, if it was written like this:
function x(argument, callback) {
if (!argument) {
return process.nextTick(callback, new Error('Bad argument'));
}
runSomeAsyncFunction(argument, (error, result) => {
if (error) {
return callback(new Error('Error in async function'));
}
callback({data: result});
});
}
it would be guaranteed that the callback will never be invoked before x() returns.
Now, if that can cause a "major breakdown" depends entirely on how it is used. If you run something like this:
let a;
x('arg', (err, result) => {
// assume that 'a' has a value
console.log(a.value);
});
// assign a value to 'a' here:
a = {value: 10};
then it will sometimes crash with the version of x() without process.nextTick and will never crash with the version of x() with process.nextTick().
how to run next function after first done with setInterval?
for example:
step1();
step2();
setInterval(step1, 1000).done(function() {
setInterval(step2, 1000).done( /* next step */);
});
please help me with solution!
Edit: This is an old answer. Now you can achieve this using promises also but the code will be slightly different.
If you don't want to use a promise you can use a simple flag to achieve such a thing. Please see example below:
var flag = true;
function step1() {
console.log('title');
}
function step2() {
console.log('subtitle');
}
function wrapper() {
if(flag) {
step1();
} else {
step2();
}
flag = !flag;
}
setInterval(wrapper, 30000);
If you want to chain functions on completion you can use callback functions.
Example:
function first(callback) {
console.log('Running first');
if (callback) {
callback();
}
}
function second() {
console.log('Running second function');
}
first(second);
The first function checks if a callback is used and then runs it. If there is no callback function nothing happens. You can chain functions this way.
You can also use anonymous functions.
first(function () {
console.log('This function that will run after the first one);
});
If you use setTimeout() you can't be sure whether the previous function has completed. A better way would be to use promises.
Understanding Promises
I hope I understood your question right. Good luck!
First of all setInterval can not be done by itself, it will fire infinitely if you not clear it with clearInterval.
But if you have some async action inside your function and whant to wait for it and then call another function you may just promisify it like Avraam Mavridis suggested.
function step1() {
var deferred = $.Deferred();
setTimeout(function () {
alert('I am step 1');
deferred.resolve();
}, 1000);
return deferred.promise();
}
function step2() {
alert('I am step 2');
}
step1().done(step2);
JsFiddle
It is possible to determine the order of TWO tasks using callbacks, as shown below.
a(b);
function a(callback) {
// do something
callback();
}
function b() {
// do next
}
See Fiddle
First do a(), then do b().
I would like to concatenate more than two tasks.
As I´m dealing with quite big functions, I´m looking for something like that:
a(b(c));
First do a(), then do b(), then do c().
However I'm not successful with this. See Fiddle
Is there an easy way to do so, maybe without needing Promises?
You're calling b immediately, not passing a callback to a. You'll need to use a function expression:
a(function(aResult) {
b(c);
});
Of course, you can avoid these by returning closures from all your functions:
function a(callback) {
return function(args) {
// do something
if (callback) callback(res);
};
}
function b(callback) {
return function(aResult) {
// do next
if (callback) callback(res);
};
}
function c(callback) {
return function(bResult) {
// do next
if (callback) callback(res);
};
}
which you would call like this:
a(b(c())();
(this is known as pure continuation passing style)