Understanding javascript event looping _ javascript skills

Source: Internet
Author: User
This article mainly helps you understand JS event loops and explains javascript event loops in a simple way. Interested friends can refer to the popularity of web Browser Scripting languages such as JavaScript, it is helpful for you to have a basic understanding of its event-driven interaction model and its differences from the common request-response models in Ruby, Python, and Java. In this article, I will explain some core concepts of the JavaScript concurrency model, including its event loop and message queue, hoping to improve your understanding of a language, you may already use this language but may not fully understand it.

Who wrote this article?

This article is intended for web developers who use or plan to use JavaScript on the client or server. If you are already proficient in the event loop, most of the articles in this article will be very familiar to you. For those who are not very proficient, I hope to provide you with a basic understanding, which can help you better read and write daily code.

Non-blocking I/O

In JavaScript, almost all I/O operations are non-blocking. This includes HTTP requests, database operations, and disk read/write. A single-threaded execution requires that a callback function be provided when an operation is executed at runtime, and other tasks are continued. When the operation is completed, the message is inserted into the queue together with the provided callback function. In the future, messages will be removed from the queue and the callback function will be triggered.

Although this interaction model may be familiar to developers who are used to using user interfaces, such as "mousedown," and "click" events are triggered at a certain time. This is different from the synchronous request-Response Model typically performed by server applications.

Let's compare two small pieces of code, send an HTTP request to www.google.com, and output a response to the console. First, let's look at Ruby and use Faraday (a Ruby HTTP client Development Library ):

response = Faraday.get 'http://www.google.com'puts responseputs 'Done!'

The execution path is easily tracked:

1. Execute the get method and wait for the thread to wait until the response is received.
2. Get a response from Google and return it to the caller. It is stored in a variable.
3. The value of the variable (in this example, our response) is output to the console.
4. Value: "Done! "Output to console
Let's use the Node. js and Request libraries to do the same in JavaScript:

request('http://www.google.com', function(error, response, body) { console.log(body);}); console.log('Done!');

On the surface, the actual behavior is quite different:

1. execute the request function, pass an anonymous function as the callback, and execute the callback when the response is available in the future.
2. "Done! "Output to console now
3. In the future, when the response is returned and the callback is executed, output its content to the console.
Event Loop

Decouples callers and responses so that JavaScript can do other things at runtime while waiting for asynchronous operations to complete and callback triggering. But how are these callbacks organized in the memory and executed in what order? What causes them to be called?

JavaScript runtime contains a message queue, which stores the list of messages to be processed and related callback functions. These messages are in the form of a queue to respond to the external events involved in the callback function (such as clicking the mouse or receiving the HTTP request response. For example, if you click a button but do not provide a callback function, no messages will be added to the queue.

In a loop, the queue extracts the next message (each extraction is called a "tick"). When an event occurs, the message is called back for execution.

The callback function is called in the call stack as the initialization frame (segment). Because JavaScript is single-threaded, future message extraction and processing will be stopped because all calls to the stack Are waiting for return. Subsequent (synchronous) function calls will add a new call frame to the stack (for example, the function init calls the function changeColor ).

function init() { var link = document.getElementById("foo");  link.addEventListener("click", function changeColor() {  this.style.color = "burlywood"; });} init();

In this example, When you click the "foo" element, a message (and its callback function changeColor) is inserted into the queue and the "onclick" event is triggered. When a message leaves the queue, its callback function changeColor is called. When changeColor returns (or throws an error), the event loop continues. As long as the function changeColor exists and calls back The onclick method of the "foo" element, clicking on this element will cause more messages (and related callback changeColor) to be inserted into the queue.

Queue additional message

If a function is called asynchronously in the Code (such as setTimeout), the provided callback will be executed as a part of a different message queue, it will occur in a future action of the event loop. For example:

function f() { console.log("foo"); setTimeout(g, 0); console.log("baz"); h();} function g() { console.log("bar");} function h() { console.log("blix");} f();

Due to the non-blocking feature of setTimeout, its callback will be triggered after at least 0 milliseconds, rather than being processed as part of the message. In this example, setTimeout is called and a callback function g is passed in with a delay of 0 ms before execution. When the specified time reaches (almost immediately executed), a separate message will be added to the queue (g as the callback function ). The result printed on the console is as follows: "foo", "baz", "blix", and then the next action of the event loop: "bar ". If both calls are set to setTimeout in the same call segment-the values passed to the second parameter are the same-their Callbacks are inserted into the queue in the call sequence.

Web Workers

Web Workers allows you to execute a time-consuming operation in a separate thread, so that you can release the main thread to do other things. A worker (worker thread) includes an independent message queue, event loop, and the memory space is independent of the original thread that instantiates it. The communication between the worker and the main thread passes through the message, which looks like the common traditional event code example.

First, our worker:

// our worker, which does some CPU-intensive operationvar reportResult = function(e) { pi = SomeLib.computePiToSpecifiedDecimals(e.data); postMessage(pi);}; onmessage = reportResult;

Then, the main code block exists as a script-tag in our HTML:

// our main code, in a 《script》-tag in our HTML pagevar piWorker = new Worker("pi_calculator.js?1.1.14");var logResult = function(e) { console.log("PI: " + e.data);}; piWorker.addEventListener("message", logResult, false);piWorker.postMessage(100000);

In this example, the main thread creates a worker and registers the logResult callback function to its "message" event. In worker, the reportResult function registers to its own "message" event. When the worker thread receives a message from the main thread, the worker queues A message and carries the reportResult callback function. When a message is out of the queue, a new message is sent back to the main thread, and the new message enters the queue of the main thread (with the logResult callback function ). In this way, developers can delegate cpu-intensive operations to a separate thread to free the main thread from continuing to process messages and events.

About the closure

JavaScript supports closures and allows you to register callback functions in this way. When a callback function is executed, the access to the created environment is maintained (even if a new call stack is created during callback execution ). It is interesting to understand that our callback is executed as a part of a different message, rather than the one that creates it. Take a look at the following example:

function changeHeaderDeferred() { var header = document.getElementById("header");  setTimeout(function changeHeader() {  header.style.color = "red";   return false; }, 100);  return false;} changeHeaderDeferred();

In this example, the changeHeaderDeferred function contains the variable header when executed. The setTimeout function is called. As a result, messages (with changeHeader callback) are added to the message queue and executed in about 100 milliseconds. Then, the changeHeaderDeferred function returns false to end processing of the first message, but the header variable can still be referenced through the closure instead of being garbage collected. When the second message is processed (the changeHeader function), it maintains access to the header variable declared in the external function scope. Once the second message (changeHeader function) is executed, the header variable can be recycled.

Reminder

The JavaScript event-driven interaction model is different from the request-response model that many programmers are accustomed to, but as you can see, it is not complicated. Using simple message queues and event loops, JavaScript enables developers to use a large number of asynchronously-fired (Asynchronous-trigger) callback functions when building their systems, this allows the runtime environment to process concurrent operations while waiting for external events to be triggered. However, this is just a method of concurrency.

The above is all the content of this article, hoping to help you learn.

Related Article

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.