前端--node.js简介

 

node.js简介

======================================================================================

 

什么是Nodejs

 

nodejs安装-ubantu

sudo apt-get install nodejs
sudo apt-get install npm
$ npm -v
6.14.4
$ node -v
v10.19.0


升级到最新版
npm install -g n
root@db:~# n latest

  installing : node-v14.9.0
       mkdir : /usr/local/n/versions/node/14.9.0
       fetch : https://nodejs.org/dist/v14.9.0/node-v14.9.0-linux-x64.tar.xz
   installed : v14.9.0 (with npm 6.14.8)

Note: the node command changed location and the old location may be remembered in your current shell.
         old : /usr/bin/node
         new : /usr/local/bin/node
To reset the command location hash either start a new shell, or execute PATH="$PATH"

 

# /usr/local/bin/node -v
v14.9.0

安装指定版本

n 12.9.1 

 




简单服务器

let http = require("http");

http.createServer(function (request, response) {

    // 发送 HTTP 头部
    // HTTP 状态值: 200 : OK
    // 内容类型: text/plain
    response.writeHead(200, {'Content-Type': 'text/plain'});

    // 发送响应数据 
    response.end('begin start node.js\n');
}).listen(8008);

// 终端打印如下信息
console.log('http://127.0.0.1:8008/');

 

$ node server.js 
http://127.0.0.1:8888/

 

包管理工具npm

 

升级

sudo npm install npm -g

淘宝镜像

sudo npm install -g cnpm --registry=https://registry.npm.taobao.org

 

本地安装

将安装包放在 ./node_modules 下(运行 npm 命令时所在的目录),如果没有 node_modules 目录,会在当前执行 npm 命令的目录下生成 node_modules 目录。

可以通过 require() 来引入本地安装的包。

npm install express

 

全局安装

安装包放在 /usr/local 下或者你 node 的安装目录

可以直接在命令行里使用。

如果你希望具备两者功能,则需要在两个地方安装它或使用 npm link

/usr/local/lib/node_modules

npm install express -g

 

查看安装信息

查看所有全局安装的模块
npm list -g

如果要查看某个模块的版本号,可以使用命令如下:
npm list grunt
 

使用 package.json

package.json 位于模块的目录下,用于定义包的属性。接下来让我们来看下 express 包的 package.json 文件,位于 node_modules/express/package.json 内容

 

环境变量配置

export NODE_PATH=/opt/wks/nodejs/node_modules

 

全局安装

sudo npm install -g express

$ ll /usr/local/lib/node_modules/
total 16
drwxr-xr-x 4 root root 4096 6月  25 12:08 ./
drwxr-xr-x 5 root root 4096 6月  25 11:22 ../
drwxr-xr-x 5 root root 4096 6月  25 11:22 cnpm/
drwxr-xr-x 4 root root 4096 6月  25 12:08 express/
$ ll express
total 144
drwxr-xr-x  4 root root   4096 6月  25 12:08 ./
drwxr-xr-x  4 root root   4096 6月  25 12:08 ../
-rw-r--r--  1 root root 109589 10月 26  1985 History.md
-rw-r--r--  1 root root    224 10月 26  1985 index.js
drwxr-xr-x  4 root root   4096 6月  25 12:08 lib/
-rw-r--r--  1 root root   1249 10月 26  1985 LICENSE
drwxr-xr-x 51 root root   4096 6月  25 12:08 node_modules/
-rw-r--r--  1 root root   3949 6月  25 12:08 package.json
-rw-r--r--  1 root root   4607 10月 26  1985 Readme.md

Package.json 属性说明

  • name - 包名。

  • version - 包的版本号。

  • description - 包的描述。

  • homepage - 包的官网 url 。

  • author - 包的作者姓名。

  • contributors - 包的其他贡献者姓名。

  • dependencies - 依赖包列表。如果依赖包没有安装,npm 会自动将依赖包安装在 node_module 目录下。

  • repository - 包代码存放的地方的类型,可以是 git 或 svn,git 可在 Github 上。

  • main - main 字段指定了程序的主入口文件,require('moduleName') 就会加载这个文件。这个字段的默认值是模块根目录下面的 index.js。

  • keywords - 关键字

 卸载模块

npm uninstall express

到 /node_modules/ 目录下查看包是否还存在,或者使用以下命令查看
npm ls


更新模块

npm update express
 

搜索模块

npm search express


创建模块

npm init
输入相关信息,可以生成一个package.json

在 npm 资源库中注册用户(使用邮箱注册):
npm adduser

发布模块
npm publish

版本号

NPM使用语义版本号来管理代码。语义版本号分为X.Y.Z三位,分别代表主版本号、次版本号和补丁版本号。当代码变更时,版本号按以下原则更新。
如果只是修复bug,需要更新Z位
如果是新增了功能,但是向下兼容,需要更新Y位。
如果有大变动,向下不兼容,需要更新X位。


REPL 命令

$ node
>

  • ctrl + c - 退出当前终端。

  • ctrl + c 按下两次 - 退出 Node REPL。

  • ctrl + d - 退出 Node REPL.

  • 向上/向下 键 - 查看输入的历史命令

  • tab 键 - 列出当前命令

  • .help - 列出使用命令

  • .break - 退出多行表达式

  • .clear - 退出多行表达式

  • .save filename - 保存当前的 Node REPL 会话到指定文件

  • .load filename - 载入当前 Node REPL 会话的文件内容。


回调函数

//最后一个输出
setTimeout(function () {

    let fs = require("fs");
    let data = fs.readFileSync('/opt/tmp/text.log');
    console.log(data.toString());
},1000);

//第二个输出
var fs = require("fs");
fs.readFile('/opt/tmp/text2.log', function (err, data) {
    if (err) return console.error(err);
    console.log(data.toString());
});

//第一个输出
console.log("程序执行结束!");

 

观察者模式

定义一种一对多的依赖关系;被观察者发生变化时,会通知所有的观察者

 

 

 

事件循环

Node.js 是单进程单线程应用程序
异步..支持回调函数
事件机制用观察者模式实现
单线程类似进入一个while(true)的事件循环,直到通知完所有事件观察者才退出,每个异步事件都有一个事件观察者,如果有事件发生就会通知该事件观察者(调用该回调函数).


事件驱动

nodejs是单线程,每次的web请求交由事件循环处理,事件本身处理的内容是异步的,不会占用这个循环多少时间,因此效率不低。

 

 

 

 

EventEmitter

 

// 引入 events.js 模块
let events = require('events');

// 创建 eventEmitter 对象
let eventEmitter = new events.EventEmitter();

setTimeout(function () {
    eventEmitter.emit('water');
},1000);

let waterHandler = function () {
    console.log('浇水....');
    eventEmitter.emit('flower');
};
eventEmitter.on('water', waterHandler);

eventEmitter.on('flower', function(){
    console.log('开花....。');
});

console.log("开始....");

node events.js

$ node events.js 
开始....
浇水....
开花....。

 详细参考

https://www.runoob.com/nodejs/nodejs-event.html

所有的异步 I/O 操作在完成时都会发送一个事件到事件队列
一个 net.Server 对象会在每次有新连接时触发一个事件, 一个 fs.readStream 对象会在文件被打开的时候触发一个事件。 所有这些产生事件的对象都是 events.EventEmitter 的实例。





模块系统

参考
https://www.runoob.com/nodejs/nodejs-module-system.html

文件模块缓存--> 原生模块 --> 文件模块


函数

参考

https://www.runoob.com/nodejs/nodejs-function.html

匿名函数作为参数使用

 

 Node.js 路由

route.js

var url = require("url");

function route(request) {
    let pathname = url.parse(request.url).pathname;
    let res = '';

    if (pathname=="/") {
        res = '欢迎';
    }else if (pathname=='/main'){
        let paramStr = url.parse(request.url).query;
        let params = paramSplit(paramStr);

        console.log(params);
        res = '欢迎 ' + params["name"];
    }

    return res;
}

function paramSplit(paramStr){
    let params = paramStr.split("&")
    let param = {}
    for(let i=0; i<params.length; i++){
        let kv = params[i].split("=");
        param[kv[0]] = kv[1];
    }
    return param;
}


exports.route = route;

 

server.js

var http = require("http");


function startHttp(route,port) {
    function onRequest(request, response) {


        let res = route(request);


        //这里指定编码,处理乱码的问题
        response.writeHead(200, {'Content-Type': 'text/plain;charset=utf-8'});

        response.write(res);
        response.write("\n");
        response.end();
    }

    if (port == undefined){
        port = 8008;
    }
    http.createServer(onRequest).listen(port);
    console.log("127.0.0.1:"+port);
}

exports.start = startHttp;

 

index.js

let router = require("./route");
let server = require("./server");

//server.start(router.route());
server.start(router.route,8000);

 

访问

http://127.0.0.1:8000/main?name=piao&page=3

 

$ node index.js 
127.0.0.1:8000
{ name: 'piao', page: '3' }

 

 

 get路由的另一种写法,等效于上面的一种

var url = require("url");

function route(request) {
    let pathname = url.parse(request.url).pathname;
    let res = '';

    if (pathname=="/") {
        res = '欢迎';
    }else if (pathname=='/main'){
        let paramStr = url.parse(request.url,true).query;
        console.log(paramStr.name)
        res = '欢迎 ' + paramStr.name
    }

    return res;
}


exports.route = route;

 

 

 get/post请求

 根据不同的url匹配不的方法,方法中返回回写数据,并且指定回定的格式。

  /opt/wks/nodejs_study/n01_server/src

url.parse(request.url).pathname; 表示url的前半部分
querystring.parse(post)  将参数部分解析为js对象

 

server.js

let http = require("http");

function startHttp(route,port) {
    function onRequest(request, response) {
        route(request,response);
    }

    if (port == undefined){
        port = 8008;
    }
    http.createServer(onRequest).listen(port);
    console.log("127.0.0.1:"+port);
}

exports.start = startHttp;

 

index.js
let server = require("./server");
let bsn = require("./bsn");

//server.start(router.route());
server.start(bsn.init,8000);

route.js

let url = require("url");
let querystring = require('querystring');



function Route(request,response) {

}

Route.prototype.routeGet = function (request,response,pathname,callback) {
    let path = url.parse(request.url).pathname;
    console.log(path);
    if (path == pathname){
        let data = url.parse(request.url,true).query;
        let body = callback(data);

        //这里指定编码,处理乱码的问题
        response.writeHead(200,{'Content-Type': body.type});
        response.end(body.data);
    }
}


Route.prototype.route = function (request,response,pathname,callback) {
    console.log(this.pathname);
    if (this.pathname == pathname){
        callback(request,response);
    }
}

Route.prototype.routePost = function (request,response,pathname,callback) {
    let path = url.parse(request.url).pathname;
    console.log(path);
    console.log(path == pathname);
    if (path == pathname){
        let post = '';
        // 通过req的data事件监听函数,每当接受到请求体的数据,就累加到post变量中
        request.on('data', function(chunk){
            post += chunk;
        });

        // 在end事件触发后,通过querystring.parse将post解析为真正的POST请求格式,然后向客户端返回。
        request.on('end', function(){

            let data = querystring.parse(post)
            let body = callback(data);
            //这里指定编码,处理乱码的问题
            response.writeHead(200,{'Content-Type': body.type});
            response.end(body.data);
        });
    }
}




exports.Route = Route;

 

bsn.js

let router = require("./route");
let util = require('util');



//只有请求的处理是同步的,事件之间的处理是异步的
//所有请求的数据与响应结果只能通过参数传递,不能绑定到同一个对象上
//就相当于医院只有一个挂号处,挂号完毕后,就可以各自去相应科室看病
//挂号是同步的,因为node.js是单线程,看病是异步的
function initRoute(request,response) {
    let rt = new router.Route();
    rt.routeGet(request,response,"/",indexUrl)
    rt.routeGet(request,response,"/index",indexUrl)
    rt.routePost(request,response,"/login",postData)
}


function indexUrl(data) {
    console.log("----------------------indexUrl");
    let body = {};
    let res = '欢迎来到主页';

    body.type = 'text/plain;charset=utf-8';
    body.data = res;
    return body;
}


function postData(data) {
    console.log("----------------------postData");
    let body = {};
    let postHTML =
        '<html><head><meta charset="utf-8"><title>dbm</title></head>' +
        '<body>' +
        '<form method="post">' +
        '名称: <input name="name"><br>' +
        '密码: <input name="password"><br>' +
        '<input type="submit" value="提交">' +
        '</form>' +
        '</body></html>';


    let res = '';
    if(data.name && data.password) { // 输出提交的数据
        res = util.inspect(data);
        body.type = 'text/plain;charset=utf-8';

    } else {  // 输出表单
        res = postHTML;
        body.type = 'text/html;charset=utf-8';
    }
    body.data = res;
    return body;
}


exports.init = initRoute;

 

$ node index.js
http://127.0.0.1:8000/

欢迎来到主页

http://127.0.0.1:8000/login

 

 

 

 

 

 

 

 






posted @ 2020-09-03 14:15  方诚  阅读(365)  评论(0编辑  收藏  举报