Event-driven programming in Node.js _node.js

Source: Internet
Author: User

In the traditional programming model, I/O operations are like a normal local function call: The program is blocked before the function is executed and cannot continue to run. Blocking I/O originates from an earlier time slice model where each process is like an independent person, with the aim of separating everyone from each other, and each person usually can only do one thing at a time, and must wait until the previous thing is done before deciding what to do next. But the "one user, one process" model, which is widely used in computer networks and the Internet, has a poor scalability. Managing multiple processes consumes a lot of memory, and context switching takes up a lot of resources, which is a huge burden for the operating system, and can cause a sharp falloff in system performance as the number of processes increases.

Multithreading is an alternative, threading is a lightweight process, it will share memory with other threads in the same process, which is more like an extension of the traditional model, used to execute multiple threads concurrently, when one thread waits for I/O operations, other threads can take over the CPU, and when I/O operations are complete, the threads that are waiting in front of them are awakened. That is, a running thread can be interrupted and then restored later. In addition, some system threads can run in parallel under different cores of multi-core CPUs.

Programmers do not know at what time the thread will run, they have to be careful with concurrent access to shared memory, so you must use some synchronization primitives to synchronize access to a data structure, such as using locks or semaphores, to force threads to execute with specific behaviors and schedules. For applications that rely heavily on shared state between threads, it is easy to see strange problems that are very random and difficult to find.

There is also a way to use multithreaded collaboration, you are responsible for the explicit release of the CPU, and the CPU time to other threads to use, because you personally control the thread's execution plan, thereby reducing the need for synchronization, but also improve the complexity of the program and error opportunities, but not to avoid the problems of multithreading.

What is event-driven programming

Event-driven programming (Evnet-driven programming) is a programming style by which events determine the execution flow of a program, which is handled by an event handler (events handler) or a callback (event callback). An event callback is a function that is called when a particular event occurs, such as when a database returns a query result or a user clicks a button.

Recall that in traditional blocking I/O programming patterns, database queries might look like this:

Copy Code code as follows:

result = Query (' SELECT * from posts WHERE id = 1 ');

Do_something_with (result);


The above query function keeps the current thread or process waiting until the underlying database completes the query operation and returns.

In the event-driven model, this query becomes this:

Copy Code code as follows:

query_finished = function (Result) {

Do_something_with (result);

}

Query (' SELECT * from posts WHERE id = 1 ', query_finished);

First you define a function called query_finished, which contains the things to do after the query is done. The function is then passed to the query function as a parameter, and query_finished is invoked when query completes, rather than simply returning the query results.

When an event of interest occurs, you call the function you define, rather than simply return the result, the programming model is called event-driven programming or asynchronous programming. This is the most obvious feature of node, which means that the current process is not blocked when performing I/O operations, so multiple I/O operations can be executed in parallel, and the corresponding callback function is invoked when the operation completes.

The underlying event-driven programming is dependent on the event loop, which is essentially a structure in which the event detection and event handlers trigger the constant cyclic invocation of the two functions. In each cycle, the event loop mechanism needs to detect which events have occurred, and when the event occurs, it finds the corresponding callback function and calls it.

The event loop is just a thread running within the process, and when the event occurs, the event handler can run independently and not be interrupted, which means:

1. At a certain point, there is at most one event callback function running
2. Any event processor runtime will not be interrupted

With this, developers can no longer have headaches for thread synchronization and concurrent modification of shared memory.

A well-known secret:

A long time ago, people in the system programming community knew that event-driven programming was the best way to create a high concurrency service, because it saved a lot of memory, did not have much context switching, and saved a lot of execution time.

Slowly, this idea permeates other platforms and communities, and there are some well-known event loops, such as the anyevnet of Ruby's event Machine,perl, and Python's twisted, in addition to many other implementations and languages.

Using these frameworks for development requires learning about framework-specific knowledge and framework-specific libraries, for example, when using event machine, in order to enjoy the benefits of non-blocking, you have to avoid using a synchronization class library, which can only use the asynchronous class library of event machine. If you use any of the blocking class libraries (such as most of Ruby's standard libraries), your server loses the best scalability because the event loop is still blocked and occasionally hinders the processing of I/O events.

Node was originally designed as a non-blocking I/O server platform, so in general, you should expect all the code running on it to be non-blocking. Because JavaScript is very small and it does not force any I/O model (because it does not have a standard I/O class Library), node is built in a very pure environment with no historical legacy issues.

How node and JavaScript simplify asynchronous applications

The author of node, Ryan Dahl, initially used C to develop the project, but found that the context of the maintenance function call was too complex, resulting in a high level of code complexity. Then he switched to Lua, but Lua already had a few blocked I/O class libraries, and blocking and non-blocking mixed together could confuse developers and thus hinder many people from building scalable applications, and Lua was also abandoned by Dahl. Finally he turned to the closure of the javascript,javascript and functions of the first-level objects, which made JavaScript ideal for event-driven programming. The magic of JavaScript is one of the main reasons that node is so popular.

What is closure

A closure can be understood as a special function, but it can inherit and access variables in the scope that it is defined by itself. When you pass a callback function as an argument to another function, it will be invoked later, and magically, when called, the callback function remembers the context in which it is defined and the variables in the parent context, and can access them normally. This powerful feature is the core of node success.

The following example shows how a JavaScript closure works in a Web browser. If you want to listen on a single machine event for a button, you can do this:

Copy Code code as follows:

var clickcount = 0;

document.getElementById (' MyButton '). onclick = function () {

Clickcount + 1;

Alert ("clicked" + Clickcount + "times.");

};

This is true when using jquery:

Copy Code code as follows:

var clickcount = 0;

$ (' Button#mybutton '). Click (function () {

Clickedcount + +;

Alert (' clicked ' + Clickcount + ' times. ');

});

In JavaScript, a function is the first class object, which means that you can pass a function as a parameter to another function. The above two examples, the former assigns a function to another function, the latter passes the function as an argument to another function, clicking the handler function (callback function) of the event to access each variable under the code block where the function definition resides, in which case it accesses the CLICKCOUNT variable defined within its parent closure.

The Clickcount variable is in the global scope (outermost scope of JavaScript), it saves the number of times a user clicks on a button, usually storing variables in a global scope is a bad habit because it's easy to conflict with other code, and you should put variables in the local scope that uses them. Most of the time, just wrapping the code in one function is equivalent to creating a closure, which makes it easy to avoid polluting the global environment, like this:

Copy Code code as follows:

(function () {

var clickcount = 0;

$ (' Button#mybutton '). Click (function () {

Clickcount + +;

Alert (' clicked ' + Clickcount + ' times. ');

});

}());


Note: line seventh of the above code, which is called immediately after defining a function, is a common design pattern in javascript: Creating a new scope by creating a function.

How closures help Asynchronous programming

In the event-driven programming model, write the code that will run after the event occurs, and then put the code into a function, and finally pass the function as a parameter to the caller, which is later called by the caller function.

In JavaScript, a function is not an isolated definition, and it remembers the context of the scope that is being declared, a mechanism that allows JavaScript functions to access all variables in the context of the function definition and in the parent context.

When you pass a callback function as a parameter to the caller, the function is invoked at a later time. Even though the scope that defines the callback function has ended, it can still access all the variables in the closed scope and its parent scope when the callback function is invoked. Like the last example, the callback function is called inside the jquery click (), but it still accesses the clickcount variable.

It shows the magic of closures, and passing state variables to a function allows you to do event-driven programming without maintaining the state, and JavaScript's closure mechanism helps you maintain them.

Summary

Event-driven programming is a programming model that determines program execution flow through event triggering. Programmers register callback functions (often called event handlers) for events of interest to them, and then the system invokes the registered event handler when the event occurs. This programming model has many advantages that traditional blocking programming models do not have, and it is necessary to use multiple processes/multithreading before implementing similar features.

JavaScript is a powerful language because of its first-type object's function and closure characteristics, making it ideal for event-driven programming.

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.