20.Nodejs basics (in) - December 16, 2019

December 16, 2019 18:58:55

October 4, 2019 12:20:59

Introduction 1. nodejs

Node.js is a platform to make JavaScript running in the development server, it allows JavaScript tentacles server, can equal footing with PHP, JSP, Python, Ruby.

But Node seems a bit different:

Node.js is not a separate language , with PHP, JSP, Python, Perl, Ruby is "not only a language, but also the platform" different, Node.js of using JavaScript programming , JavaScript engine runs on (V8).

● Compared with PHP, JSP, etc. (PHP, JSP, .net need to run a program on the server, the Apache, Naginx, Tomcat, IIS.), Node.js skipped Apache, Naginx, IIS and other HTTP server, its own do not build on any server software . Node.js many design and classic architecture (LAMP = Linux + Apache + MySQL + PHP) is very different, can provide a powerful scalability. While we will see, Node.js no web container.

Node.js own philosophy, it is to spend minimal hardware cost, the pursuit of higher concurrency, higher processing performance.

Features:

The so-called characteristic is the high-performance server Node.js is how to solve the bottleneck problem.

1.1 single-threaded

On the server side language Java, PHP or .net, etc., create a new thread for each client connection. And each thread takes about 2MB of memory. That is, in theory, a 8GB server can simultaneously connect maximum number of users is about 4000. Let Web applications to support more users, we need to increase the number of servers, and hardware costs, of course, Web applications on the rise.

Node.js is not connected to each client to create a new thread, but only one thread. When a user is connected, it triggers an internal event, through a non-blocking I / O, event-driven mechanism, so that the macro program Node.js also parallel. Use Node.js, a 8GB memory server that can handle more than 40,000 simultaneous user connections.

In addition, the benefits of single-threaded, as well as the operating system is no longer fully thread creation, destruction time overhead.

Harm is caused by the collapse of a user thread, the whole services have collapsed, others have collapsed.

image-20191004123038963

Multi-threading, a comparison of single-threaded.

In other words, a single thread can also cause "concurrency" on the macro.

1.2 Non-blocking I / O non-blocking I / O

For example, when the acquired data to access the database, take some time. In a traditional single-threaded processing mechanism, after the implementation of the code to access the database, the entire thread will pause and wait for the database to return the results in order to execute the code behind. In other words, I / O block the execution of the code, which greatly reduces the efficiency of the implementation of the program.

Since Node.js is adopted after the non-blocking I / O mechanism, so the code access to the database is performed, immediately behind the code is executed instead, the database returns the results of the processing code in the callback function, thereby improving the efficiency of the program.

When an I / O is finished, the form will be event notification thread of execution I / O operations and thread callback function for this event . To handle asynchronous I / O, thread must have an event loop, constantly checking there are no pending events, to be addressed in turn.

Blocking mode, a thread can only handle one task, in order to improve the throughput must be multi-threaded. The non-blocking mode, a thread always perform computing operations, the thread CPU core utilization is always 100%. So, this is a particularly philosophical solutions: its people, but a lot of people idle; your life is not like a person, Kill working children.

1.3 Event-driven event-driven

In Node, the client requests to establish a connection, to submit data and other acts, will trigger the corresponding event. In Node, in one moment, you can only execute a callback event, but an event callback function to perform in the middle, you can turn to other events (for example, another new user is connected), and then return to continue with the original event callback function, this processing mechanism, known as the "event loop" mechanism.

Node.js is the underlying C ++ (V8 is written in C ++). Underlying code, the event queue for nearly half are constructed callback queue. Event-driven scheduling server to complete the task, which is to think of the devil. Dancing on the tip, with a thread, take up the mission to deal with a lot of tasks.

image-20191004124914552

Single-threaded benefits, single-threaded, reduced memory overhead, operating system, memory paging.

If one thing has entered, but was I / O blocked, so this thread is blocked.

Non-blocking I / O , not Shadeng I / O statement ends, but will execute the statements that follow.

Non-blocking will be able to solve the problem yet? For example, the implementation of the red business, the implementation process, Xiaogang's I / O completion callback, at this time how to do? ?

Event mechanism, the event loop , whether a new user's request, or the old user I / O completion, all the way to join the event will be an event loop, waiting to be scheduled.

2. http module

2.1 Examples req, res
1//require表示引包,引包就是引用自己的一个特殊功能
2var http = require("http");

3//创建服务器,参数是一个回调函数,表示如果有请求进来,要做什么
4var server = http.createServer(function(req,res){
5   //req表示请求,request;  res表示响应,response
6   //设置HTTP头部,状态码是200,文件类型是html,字符集是utf8
7   res.writeHead(200,{"Content-type":"text/html;charset=UTF-8"});
8   res.end("哈哈哈哈,我买了一个iPhone" + (1+2+3) + "s");
9});
10
11//运行服务器,监听3000端口(端口号可以任改)
server.listen(3000,"127.0.0.1");

req request, request; res represents the response, response

If you want to change, you must interrupt the currently running server, node once again, refresh the job.

ctrl + c, you can interrupt pending server program.

You will find that our local write a js, killing can not be directly dragged into the browser to run, but with node, any one of us js file that can be run by a node. In other words, node is the execution environment of a js.

1//这个案例简单讲解http模块
2//引用模块
3var http = require("http");
4
5//创建一个服务器,回调函数表示接收到请求之后做的事情
6var server = http.createServer(function(req,res){
7   //req参数表示请求,res表示响应
8   console.log("服务器接收到了请求" + req.url);
9   res.end();
10});
11//监听端口
server.listen(3000,"127.0.0.1");
2.2 req.url

We now look at the things that can be used inside req.

The key is req.url attribute indicates the user's request URL address. All routing design, are implemented by req.url.

We are more concerned not get the URL, but recognize this URL.

识别URL,用到两个新模块,第一个就是url模块,第二个就是querystring模块

2.3 res.end(),write(),writeHead()
2.4 总结

response得先writeHead()才可以写其他语句。

res.writeHead(200,{"Content-Type":"text/html;charset=UTF8"});

3. querystring 模块

querystring.decode() == querystring.parse()

新增于: v0.1.99

querystring.decode() 函数是 querystring.parse() 的别名。

querystring.encode() == querystring.stringify()

新增于: v0.1.99

querystring.encode() 函数是 querystring.stringify() 的别名。

var querystring=require("querystring");

var string1=querystring.parse('foo=bar&abc=xyz&abc=123');
console.log(string1)

var string2=querystring.decode('foo=bar&abc=xyz&abc=123');
console.log(string2)
//[Object: null prototype] { foo: 'bar', abc: [ 'xyz', '123' ] }
3.1 querystring.parse(str[, sep[, eq[, options]]])

querystring.parse() 方法将 URL 查询字符串 str 解析为键值对的集合。

例如,查询字符串 'foo=bar&abc=xyz&abc=123' 被解析为:

{
  foo: 'bar',
  abc: ['xyz', '123']
}

querystring.parse() 方法返回的对象不是原型继承自 JavaScript Object。 这意味着典型的 Object 方法如 obj.toString()obj.hasOwnProperty() 等都没有定义并且不起作用。

3.2 querystring.stringify(obj[, sep[, eq[, options]]])

querystring.stringify() 方法通过迭代对象的自身属性从给定的 obj 生成 URL 查询字符串。

querystring.stringify({ foo: 'bar', baz: ['qux', 'quux'], corge: '' });
// 返回 'foo=bar&baz=qux&baz=quux&corge='

querystring.stringify({ foo: 'bar', baz: 'qux' }, ';', ':');
// 返回 'foo:bar;baz:qux'
3.3总结:

parse是相当于编译成json,stringfy相当于是把json变成了字符串。

4.url模块

4.1 网址构成

URL 'http://user:[email protected]:8080/p/a/t/h?query=string#hash'

image-20191004135129123

Url {
  protocol: 'http:',    // 指的是底层使用的协议是http
  slashes: true,        // 说明是否有协议的双斜线
  auth: null,
  host: 'imooc.com',    // 指的是http协议的一个Ip地址或者域名
  port: null,           // 端口,默认是 80 端口,如果使用了别的端口就必须指明
  hostname: 'imooc.com', // 主机名
  hash: null,            // hash值,通常对应页面上某个锚点,加#号之后将页面滚动到当前位置的
  search: null,          // 查询字符串参数
  query: null,           // 发送给http服务器的数据,通常是被等号分隔开的键值对称之为参数串
  pathname: '/course/list', // 访问资源路径名
  path: '/course/list',   // 路径
  href: 'http://imooc.com/course/list' // 没被解析的完整的超链接
}
4.2 url.parse()

使用url.parse()方法来将url解析成一个对象

url.parse()后面加一个true,可以将query参数解析成参数对象

let obj = url.parse(str,true);
var server = http.createServer(function (req, res) {
    console.log("服务器收到请求" + req.url);
    var querystring1=url.parse(req.url,true).query;
    res.end(querystring1.name+"+"+querystring1.age);
});
4.3 pathname

得到路由路径

//得到用户的路径
    var pathname = url.parse(req.url).pathname;
    //默认首页
    if(pathname == "/"){
        pathname = "index.html";
    }
    //拓展名
    var extname = path.extname(pathname);

5.fs模块

5.1 fs.readFile(),fs.readFileSync()

读文件

var fs = require("fs");

res.writeHead(200,{"Content-Type":"text/html;charset=UTF8"});

    //两个参数,第一个是完整路径,当前目录写./
    //第二个参数,就是回调函数,表示文件读取成功之后,做的事情

    fs.readFile("./test/1.txt",function(err,data){
        if(err){
            throw err;
        }
        console.log(userid + "文件读取完毕");
        res.end(data);
    });
5.2 处理图标路由的输出
//不处理小图标
    if(req.url == "/favicon.ico"){
        return;
    }
5.3 mkdir(),mkdirSync()

异步地创建目录。 除了可能的异常,完成回调没有其他参数。

可选的 options 参数可以是指定模式(权限和粘滞位)的整数,也可以是具有 mode 属性和 recursive 属性(指示是否应创建父文件夹)的对象。

// 创建 /tmp/a/apple 目录,无论是否存在 /tmp 和 /tmp/a 目录。
fs.mkdir('/tmp/a/apple', { recursive: true }, (err) => {
  if (err) throw err;
});
5.4 fs.stat类

stats.isDirectory()

如果 fs.Stats 对象描述文件系统目录,则返回 true

stats.isFile()

如果 fs.Stats 对象描述常规文件,则返回 true

fs.stat("./album/" + thefilename , function(err,stats){
                //如果他是一个文件夹,那么输出它:
                if(stats.isDirectory()){
                    wenjianjia.push(thefilename);
                }
5.5 fs.readdir(path[, options], callback)

读取目录的内容。 回调有两个参数 (err, files),其中 files 是目录中的文件名的数组(不包括 '.''..')。

可选的 options 参数可以是指定编码的字符串,也可以是具有 encoding 属性的对象,该属性指定用于传给回调的文件名的字符编码。 如果 encoding 设置为 'buffer',则返回的文件名是 Buffer 对象。

如果 options.withFileTypes 设置为 true,则 files 数组将包含 [fs.Dirent] 对象。

path <string> | <Buffer> | <URL>
options <string> | <Object>

    encoding <string> 默认值: 'utf8'。
    withFileTypes <boolean> 默认值: false。
callback <Function>

    err <Error>
    files <string[]> | <Buffer[]> | <fs.Dirent[]>
5.6 异步编程思想——循环语句,异步语句

错误输出:循环语句嵌套异步,输出出错

var server = http.createServer(function(req,res){
    //不处理小图标
    if(req.url == "/favicon.ico"){
        return;
    }
    //存储所有的文件夹
    var wenjianjia = [];
    //stat检测状态
    fs.readdir("./album",function(err,files){
        //files是个文件名的数组,并不是文件的数组,表示./album这个文件夹中的所有东西
        //包括文件、文件夹
        for(var i = 0 ; i < files.length ;i++){
            var thefilename = files[i];
            //又要进行一次检测
            fs.stat("./album/" + thefilename , function(err,stats){
                //如果他是一个文件夹,那么输出它:
                if(stats.isDirectory()){
                    wenjianjia.push(thefilename);
                }
                console.log(wenjianjia);
            });
        }
    });
});
5.7 把异步变成同步

使用迭代器iterator()

迭代器就是强行把异步的函数,变成同步的函数

var http = require("http");
var fs = require("fs");

var server = http.createServer(function(req,res){
    //不处理收藏夹小图标
    if(req.url == "/favicon.ico"){
        return;
    }
    //遍历album里面的所有文件、文件夹
    fs.readdir("./album/",function(err,files){
        //files : ["0.jpg","1.jpg" ……,"aaa","bbb"];
        //files是一个存放文件(夹)名的数组
        //存放文件夹的数组
        var wenjianjia = [];
        //迭代器就是强行把异步的函数,变成同步的函数
        //1做完了,再做2;2做完了,再做3
        (function iterator(i){
            //遍历结束
            if(i == files.length){
                console.log(wenjianjia);
                return;
            }
            fs.stat("./album/" + files[i],function(err,stats){
                //检测成功之后做的事情
                if(stats.isDirectory()){
                    //如果是文件夹,那么放入数组。不是,什么也不做。
                    wenjianjia.push(files[i]);
                }
                iterator(i+1);
            });
        })(0);
    });
    res.end();
});

server.listen(3000,"127.0.0.1");

6. path模块

path 模块提供用于处理文件路径和目录路径的实用工具。

6.1 dirname(path)

path.dirname()Method returns paththe name of the directory, similar to the Unix dirnamecommand.

path.dirname('/foo/bar/baz/asdf/quux');
// 返回: '/foo/bar/baz/asdf'
6.2 path.extname(path)

path.extname()Method returns the pathextension, the emergence from the last .(period) character to paththe string part of the final end. If paththe last part not ., or if the pathbase name in addition to the first character is not .an empty string is returned.

path.extname('index.html');
// 返回: '.html'

path.extname('index.coffee.md');
// 返回: '.md'

path.extname('index.');
// 返回: '.'

path.extname('index');
// 返回: ''

path.extname('.index');
// 返回: ''

path.extname('.index.md');
// 返回: '.md'
6.3 path.join([...paths])

path.join()The method of platform-specific delimiter used as delimiters given all pathpath segments connected together, and the resulting normalized.

Zero-length pathsegments are ignored. If the path is a string concatenation zero-length string is returned '.', indicating the current working directory.

path.join('/foo', 'bar', 'baz/asdf', 'quux', '..');
// 返回: '/foo/bar/baz/asdf'

path.join('foo', {}, 'bar');
// 抛出 'TypeError: Path must be a string. Received {}'
6.4 path.parse(path)

path.parse()Method returns an object whose properties represent pathan important element.

path.parse('/home/user/dir/file.txt');
// 返回:
// { root: '/',
//   dir: '/home/user/dir',
//   base: 'file.txt',
//   ext: '.txt',
//   name: 'file' }
6.5 static resource file management
var http = require("http");
var url = require("url");
var fs = require("fs");
var path = require("path");

http.createServer(function(req,res){
    //得到用户的路径
    var pathname = url.parse(req.url).pathname;
    //默认首页
    if(pathname == "/"){
        pathname = "index.html";
    }
    //拓展名
    var extname = path.extname(pathname);

    //真的读取这个文件
    fs.readFile("./static/" + pathname,function(err,data){
        if(err){
            //如果此文件不存在,就应该用404返回
            fs.readFile("./static/404.html",function(err,data){
                res.writeHead(404,{"Content-type":"text/html;charset=UTF8"});
                res.end(data);
            });
            return;
        };
        //MIME类型,就是
        //网页文件:  text/html
        //jpg文件 :   image/jpg
        var mime = getMime(extname);
        res.writeHead(200,{"Content-type":mime});
        res.end(data);
    });

}).listen(3000,"127.0.0.1");

function getMime(extname){
    switch(extname){
        case ".html" :
            return "text/html";
            break;
        case ".jpg" : 
            return "image/jpg";
            break;
        case ".css":
            return "text/css";
            break;
    }
}

October 4, 2019 16:56:17

Guess you like

Origin www.cnblogs.com/oneapple/p/12050722.html