How do functions that receive callbacks be executed in a specific order?

Asked

Viewed 269 times

0

Let’s analyze the code snippet below, in Javascript:

function rand(min = 1000, max = 4000){
        return Math.floor(Math.random() * (max - min) + min)
    }
    
    function f1(callback){
        setTimeout(function(){
            console.log('f1')
            if(callback)
                callback()
        }, rand())
    }
    
    function f2(callback){
        setTimeout(function(){
            console.log('f2')
            if(callback)
                callback()
        , rand()})
    }
    
    function f3(callback){
        setTimeout(function(){
            console.log('f3')
            if(callback)
                callback()
        }, rand())
    }
    
    f1(function(){
        f2(function(){
            f3(function(){
                console.log('Terminei')
            })
        })
    })

In F1 call, we pass a callback function, which is an anonymous function. This, in turn, calls function F2(), passing another callback function. Inside this callback function passed to F2(), a call to F3() occurs, passing to the same other callback function. In the latter function past callback, we executed the console.log('Terminei').

Following this scheme, we have the guarantee that the function F3() will always be the last to be executed, already that, in defining these functions, they receive a callback - and perform that callback last.

However, replacing the call to function F1() with the following code: f1(f2(f3(console.log('Terminei.'))), I DON’T GET THE SAME RESULT AS BEFORE, WITH THE USE OF PAST ANONYMOUS FUNCTIONS AS ARGUMENTS, that is, when I don’t use anonymous functions, I have no guarantee that the last function to perform will be F3() and the first, F1().

In this way, I wanted to know the difference between passing an anonymous function (which calls an X function) and the X function itself to a function that receives a callback. Why is there a difference in the execution flow (this is one function did not wait for the other to finish to display its text), in this case?

1 answer

3

I answered what was in the original question. Which was even answered equal, but briefly in How to determine the order of executing callbacks functions without resorting to anonymous functions and how the JS function execution stack works? and the answer was accepted. even after editions the answer still makes statements that are not demonstrated, and in fact everything was compromised. I leave the content here for people who want to know what was originally asked take advantage.


No, you can pass a normal function, but this function is the one that will be executed as callback. When you passed an anonymous function was what you wanted. When you passed the function log() of console wasn’t what you wanted, so the result you hoped didn’t happen.

When you pass any function it will be executed, and of course it needs to be compatible with what will be called internally as callback. So if the call does not use arguments, a function that does not accept arguments is what should be passed. Just as if passing an argument the function to be passed should receive an argument, and so on. And it’s not enough to be the same number of parameters that the function has in relation to the number of arguments passed, it needs to have consistency. You have to be the right guy, you can’t text if you’re going to have a percentage calculated. Can’t pass a street number when you expect the value of a installment, need to make sense.

Everything has to do with the use of arguments in the call. I will explain in detail.

What you did makes no sense. What function did you pass in the second example (not posted)? Was the console.log(), Right? And it is she who will be called, and was called, even if you have not seen. No mistake. When you get to the line callback() of function f3() is exactly the console.log() which will be executed. But what are you having printed? Nothing. And that’s what you print on the console. Who determined what to pass as argument is who calls and who called is passing anything.

For some reason you think the argument 'Terminei' is being passed along with the function and for some magical reason the call would consider this, but none of this happens. In another language this syntax would probably give error, but JS allows you to write even then that argument will be ignored. It does not go along with the function. That’s the same as passing anything, because that’s exactly what happens.

In fact this code should be like this:

f1(f2(f3(console.log)))

It is now clearer that you are passing the function and not the argument. It gives anyway, but it is more readable so because it passes the correct intention.

And then it doesn’t happen that I was expecting it, it ends up printing nothing, but there’s an impression, it’s nothing because nothing was passed in the call.

But I will give an example that does what you want without using anonymous function. I will create a function without parameters that does what you want and I will use it as callback, is not an anonymous function:

function rand(min = 1, max = 2){
    return Math.floor(Math.random() * (max - min) + min)
}

function f1(callback){
    setTimeout(function(){
        console.log('f1')
        if(callback)
            callback()
    }, rand())
}

function f2(callback){
    setTimeout(function(){
        console.log('f2')
        if(callback)
            callback()
    , rand()})
}

function f3(callback){
    setTimeout(function(){
        console.log('f3')
        if(callback)
            callback()
    }, rand())
}

function imprime() {
    console.log('Terminei.')
}

f1(f2(f3(imprime)));

I put in the Github for future reference.

You may be thinking that then you always need to create a function to pass. Also no, I just created one to match the intention, make sense. I can send you the job straight, as long as you want something a little different:

function rand(min = 1, max = 2){
    return Math.floor(Math.random() * (max - min) + min)
}

function f1(callback){
    setTimeout(function(){
        console.log('f1')
        if(callback)
            callback()
    }, rand())
}

function f2(callback){
    setTimeout(function(){
        console.log('f2')
        if(callback)
            callback()
    , rand()})
}

function f3(callback){
    setTimeout(function(){
        console.log('f3')
        if(callback)
            callback('Terminei.')
    }, rand())
}

f1(f2(f3(console.log)));

I put in the Github for future reference.

Again, who calls determines which arguments will be passed.

Remember that the callback is a delay in execution, when it is ordered to execute the state is used. It is the same problem that some people do not understand because a loop always takes the end value and not each variable value when it is transferred to a callback (more detailed).

  • I think my question was misunderstood. I will try to explain it in another way. My intention is that functions F1(), F2() and F3() are executed IN EXACTLY THAT ORDER. Remembering that the three functions receive a callback and first execute the console.log within their body and then make a call to the received callback. If you pay attention, I set random times, through the setTimeout for each one, because I want to simulate a real situation (where we do not know the execution time for each function - a request, for example).

  • however, when I use anonymous functions, calling, within anonymous functions, the next function, the result is waiting: A FUNCTION BEING EXECUTED ONLY AFTER THE PREVIOUS ONE HAS BEEN EXECUTED. However, this is not what happens when I call the functions without using anonymous functions as argument. That’s what I’d like to know: because the execution flow changes when I don’t use anonymous functions as an argument, that is, because a function didn’t wait for the one before it ended to then be executed.

  • I think it was not misunderstood, she seems very clear. It may be that you did not understand what you asked because you wanted to ask something else. We can only answer what was asked and the question is in the title and at the end. That is what I answered, if that is not what I wanted to ask, I should have asked another question. All that you have just said has nothing to do with your question. And expecting anything to do with something random doesn’t make sense. The example is even bad to indicate what you want in the question asked. This is an artificial situation. You haven’t asked what’s at the end of the comment now.

  • Nor did it demonstrate that there is a difference in the flow of execution, it only put one code, it did not put the other one, and it did not show the difference, it just said it does. There’s no way to answer what you’ve shown. What’s easy to observe is that the change you claim to have made doesn’t print anything and I explained why. To tell you the truth if you want to know something else the question makes little sense, in the form made there is no relation of cause and effect that you think you have. The problem is one and you think it’s another. But it’s all too confusing for me to put away.

  • Including his statement quando eu não uso funções anônimas, não tenho garantia de que a última função a executar será a f3() e a primeira, a f1() doesn’t make sense because you don’t have the same guarantee in any case, you put a random situation in the play. It made the execution order unpredictable regardless of how you make the call. It may have given a match in some case, but no guarantee. It’s the old problem of people believing that what they saw worked is right, even if it isn’t. I just executed and c/anonymous function was out of order and c/a normal was in order.It was already different

  • Negative, if you read my question, you will see that in the penultimate paragraph I wrote, in bold, that I get different results if I use anonymous functions as an argument. Moreover, in the last paragraph, I ask why the EXECUTION FLOW, in this example, changes when I use anonymous functions. EU I SAY THAT, IN ONE WAY (using anonymous functions), A FUNCTION IS NECESSARILY EXECUTED ONLY AFTER THE END OF THE OTHER; WHEN I DO NOT USE ANONYMOUS FUNCTIONS, THAT ORDER IS NOT MAINTAINED.

  • Saying that you get it is different from showing. You keep saying it and not showing it. I got a different result. And again anything that involves randomness cannot be used to find determinism, by definition it cannot..

  • f1(function(){
 f2(function(){
 f3(function(){
 console.log('Terminei.')
 })
 })
}) Did you run that way? Because here I’ve done 1000 tests and always comes out in order.

  • It’s there in the answer running. The whole question is that you asked about the need to use anonymous function in callback and that’s what I said, you talk all the time if you’re forced to wear one, and I showed you don’t need.

  • @emanoellucas your question is "In Javascript, for a function that receives a callback, we must always pass an anonymous function?". The answer was no, one can pass declared functions followed by the explanation. From what I’m reading you were wrong in formulating the question, your question I think should be something like this : "How the Javascript function call stack works?" or else "How to determine the execution order of nested callbacks?" that surely the answer obtained would be another.

  • @emanoellucas For what you asked the answer is correct and both the answer and the question are helpful to the community. Now I’m sorry it didn’t go as expected. Ask another question using the same code.

  • @Augustovasques, that’s right, thank you. I’ll rephrase the question!

  • 3

    Now it was clear that the question was the one I answered, I did not understand what happened here. He asked another question that gave the same answer without details and she was accepted. That answer does not speak anything of what was said up here and it was considered right, on the contrary, it speaks of the argument that I spoke here and now stressed that this is it, I just gave more details. I think.

  • @Maniero I tried to help but I think I got worse. I didn’t understand what the AP wants. I am not going to make any more comments which, even if serious, will appear to be a mockery. I would ask PA to explain further how the other question satisfied him.

  • @Maniero, in the third paragraph of your answer you say that nothing is printed, when in fact it is a lie, I said that about 30 times during the text of the question. It’s printed, but not in the order I expected. First you said that my question did not express what I wanted to know, then I changed the question, then you went and closed the question, and your answer did not resolve my doubt, nor did it touch the point I wanted. For the third time, I asked the question again, but you closed it, I think it was for whimsy. Fortunately, someone answered satisfactorily before it was closed.

  • The code you wrote - unlike what you say - DOESN’T DO WHAT I WANT. What I want is for it to run, ALWAYS, "F1, F2, F3, I’m finished". IN ORDER. YOUR CODE DOES NOT DO THAT!!!!!!!!!!!!!!!!!!!!! IS IN MY QUESTION, CAN I UNDERSTAND THAT WHAT I WANT IS THAT ORDER BE RESPECTED AND I DON’T NEED TO USE ANONYMOUS FUNCTIONS! SIMPLE.

  • 2

    This is the last time I write here because you look allegored and don’t want to progress the conversation. He has done one wrong thing after another to want to impose something he cannot. I answered what he asked initially. You have already made it clear that you did not like, you have already denied the answer, you have made changes that you should not because an answer had already been given on top of what you asked. It didn’t help your situation that you had to accept an answer to an equal question and answer the same question I was answering here, nothing you’re talking about right now. So your comments don’t make sense.

  • 3

    You already got an answer you wanted there in the other question, so forget that question, it stayed for anyone who wants to learn something about what you asked originally. You have already made it clear that you were not satisfied here and that you stayed there on the other question. The subject is closed. Do not insist, it makes no sense.

Show 13 more comments

Browser other questions tagged

You are not signed in. Login or sign up in order to post.