When is JavaScript synchronous?

前端 未结 7 2005
孤独总比滥情好
孤独总比滥情好 2020-11-22 03:48

I have been under the impression for that JavaScript was always asynchronous. However, I have learned that there are situations where it is not (ie DOM manipulations). Is

相关标签:
7条回答
  • 2020-11-22 04:32

    To someone who really understands how JS works this question might seem off, however most people who use JS do not have such a deep level of insight (and don't necessarily need it) and to them this is a fairly confusing point, I will try to answer from that perspective.

    JS is synchronous in the way its code is executed. each line only runs after the line before it has completed and if that line calls a function after that is complete ect...

    The main point of confusion arises from the fact that your browser is able to tell JS to excute more code at anytime (simmlar to how you can excute more JS code on a page from the console). As an example JS has Callback functions who's purpose is to allow JS to BEHAVE asynchronously so further parts of JS can run while waiting for a JS function that has been executed (I.E. a GET call) to return back an answer, JS will continue to run until the browser has an answer at that point the event loop (browser) will execute the JS code that calls the callback function.

    Since the event loop (browser) can input more JS to be executed at any point in that sense JS is asynchronous (the primary things that will cause a browser to input JS code are timeouts, callbacks and events)

    I hope this is clear enough to be helpful to somebody.

    0 讨论(0)
  • 2020-11-22 04:33

    JavaScript is always synchronous and single-threaded. If you're executing a JavaScript block of code on a page then no other JavaScript on that page will currently be executed.

    JavaScript is only asynchronous in the sense that it can make, for example, Ajax calls. The Ajax call will stop executing and other code will be able to execute until the call returns (successfully or otherwise), at which point the callback will run synchronously. No other code will be running at this point. It won't interrupt any other code that's currently running.

    JavaScript timers operate with this same kind of callback.

    Describing JavaScript as asynchronous is perhaps misleading. It's more accurate to say that JavaScript is synchronous and single-threaded with various callback mechanisms.

    jQuery has an option on Ajax calls to make them synchronously (with the async: false option). Beginners might be tempted to use this incorrectly because it allows a more traditional programming model that one might be more used to. The reason it's problematic is that this option will block all JavaScript on the page until it finishes, including all event handlers and timers.

    0 讨论(0)
  • 2020-11-22 04:33

    "I have been under the impression for that JavaScript was always asynchronous"

    You can use JavaScript in a synchronous way, or an asynchronous way. In fact JavaScript has really good asynchronous support. For example I might have code that requires a database request. I can then run other code, not dependent on that request, while I wait for that request to complete. This asynchronous coding is supported with promises, async/await, etc. But if you don't need a nice way to handle long waits then just use JS synchronously.

    What do we mean by 'asynchronous'. Well it does not mean multi-threaded, but rather describes a non-dependent relationship. Check out this image from this popular answer:

             A-Start ------------------------------------------ A-End   
               | B-Start -----------------------------------------|--- B-End   
               |    |      C-Start ------------------- C-End      |      |   
               |    |       |                           |         |      |
               V    V       V                           V         V      V      
    1 thread->|<-A-|<--B---|<-C-|-A-|-C-|--A--|-B-|--C-->|---A---->|--B-->| 
    

    We see that a single threaded application can have async behavior. The work in function A is not dependent on function B completing, and so while function A began before function B, function A is able to complete at a later time and on the same thread.

    So, just because JavaScript executes one command at a time, on a single thread, it does not then follow that JavaScript can only be used as a synchronous language.

    "Is there a good reference anywhere about when it will be synchronous and when it will be asynchronous"

    I'm wondering if this is the heart of your question. I take it that you mean how do you know if some code you are calling is async or sync. That is, will the rest of your code run off and do something while you wait for some result? Your first check should be the documentation for whichever library you are using. Node methods, for example, have clear names like readFileSync. If the documentation is no good there is a lot of help here on SO. EG:

    How to know if a function is async?

    0 讨论(0)
  • 2020-11-22 04:36

    JavaScript is single-threaded, and all the time you work on a normal synchronous code-flow execution.

    Good examples of the asynchronous behavior that JavaScript can have are events (user interaction, Ajax request results, etc) and timers, basically actions that might happen at any time.

    I would recommend you to give a look to the following article:

    • How JavaScript Timers Work

    That article will help you to understand the single-threaded nature of JavaScript and how timers work internally and how asynchronous JavaScript execution works.

    0 讨论(0)
  • 2020-11-22 04:46

    JavaScript is single threaded and has a synchronous execution model. Single threaded means that one command is being executed at a time. Synchronous means one at a time i.e. one line of code is being executed at time in order the code appears. So in JavaScript one thing is happening at a time.

    Execution Context

    The JavaScript engine interacts with other engines in the browser. In the JavaScript execution stack there is global context at the bottom and then when we invoke functions the JavaScript engine creates new execution contexts for respective functions. When the called function exits its execution context is popped from the stack, and then next execution context is popped and so on...

    For example

    function abc()
    {
       console.log('abc');
    }
    
    
    function xyz()
    {
       abc()
       console.log('xyz');
    }
    var one = 1;
    xyz();
    

    In the above code a global execution context will be created and in this context var one will be stored and its value will be 1... when the xyz() invocation is called then a new execution context will be created and if we had defined any variable in xyz function those variables would be stored in the execution context of xyz(). In the xyz function we invoke abc() and then the abc() execution context is created and put on the execution stack... Now when abc() finishes its context is popped from stack, then the xyz() context is popped from stack and then global context will be popped...

    Now about asynchronous callbacks; asynchronous means more than one at a time.

    Just like the execution stack there is the Event Queue. When we want to be notified about some event in the JavaScript engine we can listen to that event, and that event is placed on the queue. For example an Ajax request event, or HTTP request event.

    Whenever the execution stack is empty, like shown in above code example, the JavaScript engine periodically looks at the event queue and sees if there is any event to be notified about. For example in the queue there were two events, an ajax request and a HTTP request. It also looks to see if there is a function which needs to be run on that event trigger... So the JavaScript engine is notified about the event and knows the respective function to execute on that event... So the JavaScript engine invokes the handler function, in the example case, e.g. AjaxHandler() will be invoked and like always when a function is invoked its execution context is placed on the execution context and now the function execution finishes and the event ajax request is also removed from the event queue... When AjaxHandler() finishes the execution stack is empty so the engine again looks at the event queue and runs the event handler function of HTTP request which was next in queue. It is important to remember that the event queue is processed only when execution stack is empty.

    For example see the code below explaining the execution stack and event queue handling by Javascript engine.

    function waitfunction() {
        var a = 5000 + new Date().getTime();
        while (new Date() < a){}
        console.log('waitfunction() context will be popped after this line');
    }
    
    function clickHandler() {
        console.log('click event handler...');   
    }
    
    document.addEventListener('click', clickHandler);
    
    
    waitfunction(); //a new context for this function is created and placed on the execution stack
    console.log('global context will be popped after this line');
    

    And

    <html>
        <head>
    
        </head>
        <body>
    
            <script src="program.js"></script>
        </body>
    </html>
    

    Now run the webpage and click on the page, and see the output on console. The output will be

    waitfunction() context will be popped after this line
    global context will be emptied after this line
    click event handler...
    

    The JavaScript engine is running the code synchronously as explained in the execution context portion, the browser is asynchronously putting things in event queue. So the functions which take a very long time to complete can interrupt event handling. Things happening in a browser like events are handled this way by JavaScript, if there is a listener supposed to run, the engine will run it when the execution stack is empty. And events are processed in the order they happen, so the asynchronous part is about what is happening outside the engine i.e. what should the engine do when those outside events happen.

    So JavaScript is always synchronous.

    0 讨论(0)
  • 2020-11-22 04:49

    Is synchronous on all cases.

    Example of blocking thread with Promises:

      const test = () => new Promise((result, reject) => {
        const time = new Date().getTime() + (3 * 1000);
    
        console.info('Test start...');
    
        while (new Date().getTime() < time) {
          // Waiting...
        }
    
        console.info('Test finish...');
      });
    
      test()
        .then(() => console.info('Then'))
        .finally(() => console.info('Finally'));
    
      console.info('Finish!');
    

    The output will be:

    Test start...
    Test finish...
    Finish!
    
    0 讨论(0)
提交回复
热议问题