前端--node.js简介
node.js简介
======================================================================================
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