How do I set a specific order of execution when asynchronous calls are involved?

后端 未结 4 762
[愿得一人]
[愿得一人] 2021-01-07 08:13

I am new(2 days!!) to the world of JavaScript and my only prior coding experience is in Java where execution of statements takes place sequentially. I understand that or at

相关标签:
4条回答
  • 2021-01-07 08:28

    I have modified your code as below to get the desired output.

    console.log("Beginning");
    function Test(callback){
    
        console.log("Something that takes a lot of time");
        setTimeout(callback,5000);
     }
    
    function tstCallBack(){
       console.log("Should come last");
    }
    Test(tstCallBack);
    

    setTimeout takes a callback function that will be executed after the specified time interval

    The use of setTimeout is the asynchronous part. When the above code is executed,first the "Begining" console statement is printed and then the Test function is called passing in a function that needs to be executed asynchronously after 500ms .

    0 讨论(0)
  • 2021-01-07 08:46

    Place the callback inside setTimeout and not outside as the callback will be executed first before the setTimeout does as javascript won't wait for setTimeout execution(as JS is synchronous by nature) and executes the next line and hence you won't get the desired output.

    console.log("Beginning");
    function Test(callback){
       setTimeout(function(){
        console.log("Something that takes a lot of time");
        callback();
       },5000);
     }
    function tstCallBack(){
       console.log("Should come last");
    }
    Test(tstCallBack);
    

    Demo

    0 讨论(0)
  • 2021-01-07 08:54

    Let's clear some things up in what you said:

    I am new(2 days!!) to the world of JavaScript and my only prior coding experience is in Java where execution of statements takes place sequentially. I understand that or at least I've read that JavaScript is asynchronous which means that if there is a statement that takes a long time to execute, the next statement is executed without holding up the program for the first statement.

    This is not how it works. A given function is either asynchronous or its synchronous by design. It has absolutely nothing to do with how long it takes to execute. You can have a very quick async function or a very long synchronous function. What determines whether the function is asynchronous or not is how it is designed. If it uses async I/O or timers or any other async infrastructure, then at least some of the execution of the function is asynchronous. That means that some of the function will finish LATER and some of the code right after this function call will execute BEFORE the async portion finishes.

    I came across callbacks(a lot actually!!) but I couldn't see how they could be used to determine the order of execution. I wrote a piece of code just to understand how it could be done and I sure could use some help.

    Callbacks are used to notify the calling code when some asynchronous operation has completed. This can be used either to consume the result of the asynchronous operation or can be used to execute the next piece of code that wants to run in sequence after the async operation has finished.

    In your code example, if you want the desired sequence, then you must call the callback inside the setTimeout() callback so that it gets called AFTER the setTimeout() called executes, thus giving you the desired sequence.

    You also have to remove the callback argument to the setTimeout callback. That callback is not passed with that argument so declaring it there is just wrong. It can be accessed directly from the parent function via a closure as shown here:

    console.log("Beginning");
    
    function Test(callback){
       setTimeout(function(){
           console.log("Something that is asynchronous");
           // call the callback here to indicate to the calling code
           // that the asynchronous operation is now complete
           callback();
       },5000);
       console.log("After Setting Timer");
    }
    
    function tstCallBack(){
        console.log("Should come last");
    }
    
    Test(tstCallBack);
    

    This will generate a sequence in the console of:

    Beginning

    After Setting Timer

    Something that is asynchronous

    Should come last


    Conceptually, the Javascript engine runs a single thread and that single thread uses an event queue. So, in your function above, this is what happens.

    1. The first console.log("Beginning"); is executed.
    2. Test(tstCallback) is called.
    3. As part of executing the Test() function, a timer is scheduled. This registers a timer internal to the JS engine.
    4. The execution of code in Test() continues, console.log("After Setting Timer"); is executed and then that function finishes.
    5. The current thread of JS execution finishes and if there is nothing else in the event queue, then the JS engine has nothing to do, but wait for the next event to occur.
    6. Some time later (the 5 seconds that your timer is set for), the internal timer fires and it puts the timer event in the JS event queue.
    7. Since there is no other JS executing at the moment, the timer event is pulled out of the event queue and executed. This means that the original callback that was registered for the timer is called.
    8. As the timer callback is called, it executes the console.log("Something that is asynchronous"); line and then calls callback().
    9. Your tstCallback function is then called and console.log("Should come last"); is executed.
    10. The async event finishes execution and the JS engine looks to see if there are any more events in the event queue. If so, the next event is pulled out of the queue and it is run.

    There are a number of very good references on how Javascript handles asynchronous operations:

    How does JavaScript handle AJAX responses in the background?

    How Javascript Timers Work

    Do I need to be concerned with race conditions with asynchronous Javascript?

    0 讨论(0)
  • 2021-01-07 08:54

    A lot of what you've said is wrong. JavaScript is sequential in the same way as Java, but asynchronous calls are made more often. If you want your callback to be called after the long thing, you must call it after the long running program. Like so -

    console.log("Beginning");
    function Test(callback){
       setTimeout(function(callback){
        console.log("Something that takes a lot of time");
        callback();
       },5000);
    
     }
    function tstCallBack(){
       console.log("Should come last");
    }
    Test(tstCallBack);
    
    0 讨论(0)
提交回复
热议问题