内容:

1.node.js介绍

2.node.js内置常用模块

3.node.js数据交互

一、node.js介绍

(1)node.js特点

与其他语言相比,有以下优点:

  • 对象、语法和JavaScript一模一样,易于前端使用
  • 相比PHP、Java、python,性能还可以
  • 前后端配合方便
  • 非阻塞、异步的交互

当然,也有缺点:比如说库支持不如Java丰富,和js一样是单线程单进程

(2)node.js安装

下载对应你系统的Node.js版本:https://nodejs.org/en/download/,选安装目录进行安装即可
安装完毕测试如下:

(3)node.js用处

  • 服务器 - 小型后台系统、中间层
  • 做工具(测试、构建、抓取) - grunt、gulp、WebPack

(4)运行node

创建一个node文件夹,然后在文件夹下写入1.js:

 let a = 12;
let b = 5; console.log(a+b)

然后在命令行中进入node目录下运行该文件:node 1.js  注:node运行文件:node  xxx.js

运行结果如下:

 

二、node.js内置常用模块

1.断言——assert

 const assert = require("assert")

 function sum(a, b){
// assert(判断, "xxx") 判断为假输出后面的信息
assert(arguments.length==2, "必须传两个参数")
assert(typeof a == 'number', "第一个参数必须是数字")
assert(typeof b == 'number', "第二个参数必须是数字") return a+b
} console.log(sum(2, 5))
// 执行下面人任意一句将报错:
// console.log(sum(2, '1'))
// console.log(sum(3))

2.Buffer和File System模块

  • buffer:曾经是node中的模块,后来融入到node本身之中了,处理二进制
  • file system:处理文件(读写文件)

file system使用实例:

 const fs = require("fs")

 // 读取文件
fs.readFile('1.txt', function(err, data){
if(err){
console.log("有错!");
} else {
console.log(data);
console.log(data.toString());
} }) // 写文件
fs.writeFile('2.txt', 'xxx', function(err){
if (err) {
console.log(err);
} else {
console.log("成功!");
}
})

注意:图片不要将二进制转成字符串,这样做会导致图片格式丢失

获取文件详细信息:

 const fs = require('fs')

 fs.stat('1.txt', function (err, stat) {
if(err){
console.log('获取文件信息失败')
} else{
console.log(stat) // detail info
console.log(stat.mtime.toGMTString()) // 修改时间
}
})

Buffer基础使用:

 let a = new Buffer('abc');
let b = new Buffer('ddd');
console.log(a, b)
// <Buffer 61 62 63> <Buffer 64 64 64> let c = Buffer.concat([a, b]);
console.log(c);
// <Buffer 61 62 63 64 64 64>

Buffer数据操作:

 // 查找
let a=new Buffer('abccc-=-dddder-=-qwerqwer');
console.log(a.indexOf('-=-')); // 截取
let b=new Buffer('abccc-=-dddder-=-qwerqwer');
console.log(b.slice(0, 5).toString()); // 切分 --> 目前buffer自带的操作中没有可以直接用的split
let c=new Buffer('abccc-=-dddder-=-qwerqwer'); Buffer.prototype.split=Buffer.prototype.split||function (c){ // 如果buffer有split就用buffer自带的split,没有就用下面的函数
let arr=[]; let cur=0;
let n=0;
while((n=this.indexOf(c, cur))!==-1){
arr.push(this.slice(cur, n));
cur=n+c.length;
} arr.push(this.slice(cur)); return arr;
}; let arr=c.split('-=-');
console.log(arr);
console.log(arr.map(buffer=>buffer.toString()));

3.C++ Addons - 用C语言/C++写插件给node用

4.多进程

理论上JavaScript是单进程单线程的,可以通过以下模块实现多进程:

  • Child Processes
  • Cluster
  • Process

注:node中没有多线程的直接实现(为了考虑安全性、应用性)

(1)进程与线程

  • 进程:进程拥有独立的执行空间和存储空间
  • 线程:同一个进程内的所有线程共享一套空间、代码
  • 多进程:成本高(慢)、安全(进程间隔离)、进程间通信麻烦、写代码简单、PHP、node
  • 多线程:成本低(快)、不安全(线程间共享)、线程间通信简单、写代码复杂、Java、C
  • 多进程:慢、简单、安全
  • 多线程:快、复杂、脆弱

(2)进程之间的通信方法

  • 管道
  • 共享内存
  • socket

(3)详细用法

详细用法见:https://www.cnblogs.com/wyb666/p/9704056.html

5.Crypto——散列、签名
crypto模块提供了md5、sha算法,主要用来进行加密(实质上是散列)、签名

普通加密:

 const crypto = require('crypto')

 let obj = crypto.createHash('sha1')
// 或者用md5加密:
// let obj = crypto.createHash('md5') obj.update('123456') console.log(obj.digest('hex')) # 以16进制输出数据

二次加密并加盐:

 const crypto = require('crypto')

 function md5(str){
let obj = crypto.createHash('md5')
obj.update(str) return obj.digest('hex')
} // 二级加密并加盐
console.log(md5(md5('123456') + 'asdfghjklzxcvbnm,./' ))

6.http

  • HTTP/HTTPS
  • HTTP/2

下面是用http模块搭建简单服务器的大致过程:

最简单的服务器:

 const http = require("http")

 let server = http.createServer(function(req, res){
// 路由处理
switch(req.url){
case '/aaa':
res.write('abc');
break;
case '/bbb':
res.write('dddd');
break;
case '/1.html':
res.write('<html><head></head><body>sdfasfasf</body></html>');
break;
}
res.end()
}); // 监听
server.listen(8080)

前后端代码分离的服务器(前端代码存在www文件夹下):

 const http=require('http');
const fs=require('fs'); let server=http.createServer(function(req, res){
fs.readFile(`www${req.url}`, function(err, data){
if(err){
res.write('404'); // 404页面
}else{
res.write(data);
}
res.end();
});
}); server.listen(8080);

注意:fs.readFile是一个异步操作,必须将res.end()放在readFile内,如果放在readFile外面会导致以下错误:

这个错误是因为程序不会等readFile执行完就会执行后面的end,因此要将end放在readFile内才会在读完文件后执行end

7.OS和Path

  • OS:系统相关
  • Path:处理路径
 const os=require('os');
const path=require('path'); // 输出CPU信息:
console.log(os.cpus()); // 路径相关:
let str='/var/local/www/aaa/1.png';
//dirname -> 文件夹路径
//basename -> 文件名
//extname -> 拓展名
console.log(path.dirname(str)); // /var/local/www/aaa
console.log(path.basename(str)); // 1.png
console.log(path.extname(str)); // .png

8.Events事件队列

(1)机制原理

Nodejs的大部分核心API都是基于异步事件驱动设计的,所有可以分发事件的对象都是EventEmitter类的实例。

大家知道,由于nodejs是单线程运行的,所以nodejs需要借助事件轮询,不断去查询事件队列中的事件消息,然后执行该事件对应的回调函数,有点类似windows的消息映射机制

(2)使用实例

 const Event = require("events").EventEmitter

 let ev = new Event()

 // 1、监听(接受)
ev.on('msg', function(a, b, c){
console.log('收到了msg事件', a, b, c);
}) // 2、派发(发送)
ev.emit('msg', 12, 5, 98)

(3)注意

大多数时候我们不会直接使用 EventEmitter,而是在对象中继承它。包括 fs、net、 http 在内的,只要是支持事件响应的核心模块都是 EventEmitter 的子类

这样做的原因有以下两点:
  • 具有某个实体功能的对象实现事件符合语义, 事件的监听和发射应该是一个对象的方法
  • JavaScript 的对象机制是基于原型的,支持 部分多重继承,继承 EventEmitter 不会打乱对象原有的继承关系
Events(事件)模块是Node.js的核心,许多其他模块用它来围绕着事件架构功能。由于Node.js运行在单一的线程中,任何同步代码都是阻塞的,所以如果有长时间运行的代码的话事件循环便会被阻塞。为了有效地使用Node.js编写代码,必须仔细思考自己的变成风格并遵循一些简单的规则

9.Query Strings和URL
(1)Query Strings

Query Strings:查询字符串,url中的?之后的字符串即为Query Strings

比如www.xxx.com/find?s=k&wd=123中的查询字符串就是 s=k&wd=123

querystring实例:

 const querystring = require("querystring")

 // url: www.xxx.com/find?s=k&wd=123
let obj = querystring.parse("s=k&wd=123") console.log(obj)
// 解析结果: { s: 'k', wd: '123' }

(2)URL

url模块和querystring模块不同之处:url模块解析整个url,而querystring只能解析url中问号之后的字符串

实例:

 const url = require("url")

 let obj = url.parse("www.xxx.com/find?s=k&wd=123")

 console.log(obj)
/*
输出结果:
Url {
protocol: null,
slashes: null,
auth: null,
host: null,
port: null,
hostname: null,
hash: null,
search: '?s=k&wd=123',
query: 's=k&wd=123',
pathname: 'www.xxx.com/find',
path: 'www.xxx.com/find?s=k&wd=123',
href: 'www.xxx.com/find?s=k&wd=123'
}
*/

注意:也可以像下面一样指定将query也一并解析

 const url = require("url")

 let obj = url.parse("www.xxx.com/find?s=k&wd=123", true)

 console.log(obj)
/*
输出结果:
Url {
protocol: null,
slashes: null,
auth: null,
host: null,
port: null,
hostname: null,
hash: null,
search: '?s=k&wd=123',
query: { s: 'k', wd: '123' },
pathname: 'www.xxx.com/find',
path: 'www.xxx.com/find?s=k&wd=123',
href: 'www.xxx.com/find?s=k&wd=123'
}
*/

10.网络相关模块

  • TCP-稳定  ->   Net
  • UDP-快     ->   UDP/Datagram
  • DNS          ->   域名解析相关
  • Domain     ->   域名相关

DNS解析实例:

 const dns = require("dns")

 dns.resolve("baidu.com", function(err, res){
if(err){
console.log("解析失败")
} else {
console.log(res)
} }) // 结果: [ '220.181.57.216', '123.125.115.110' ]

11.流操作——Stream

(1)什么是流

连续数据都是流:比如说视频流、网络流、文件流、语音流

(2)Stream具体操作

读取写入文件:

 const fs = require('fs')

 let rs = fs.createReadStream('1.txt')       // 读取流
let ws = fs.createWriteStream('2.txt') // 写入流 rs.pipe(ws) // 异常处理
rs.on('error', function (error) {
console.log('读取失败!')
}) // 读取完成 及 写入完成
rs.on('end', function () {
console.log('读取完成!')
}) ws.on('finish', function () {
console.log('写入完成!')
})

12.TLS/SSL

用于加密、安全

13.ZLIB
用于压缩 - gz压缩

zlib模块使用实例:

 const zlib = require('zlib')
const fs = require('fs') let rs = fs.createReadStream('jQuery.js')
let ws = fs.createWriteStream('jQuery.js.gz') let gz = zlib.createGzip() rs.pipe(gz).pipe(ws) // 异常处理
rs.on('error', function (error) {
console.log('读取失败!')
}) // 读取完成 及 写入完成
rs.on('end', function () {
console.log('读取完成!')
}) ws.on('finish', function () {
console.log('写入完成!')
})

三、node.js数据交互

web服务器三大任务:返回文件(html、css、图片等)、数据交互(get、post)、数据库,下面的部分将围绕返回文件及数据交互展开

1.返回文件

返回文件可以使用node.js中的fs模块,实例如下:

 const fs = require("fs")

 fs.readFile('1.txt', function(err, data){
if(err){
console.log("有错!");
} else {
console.log(data); // 二进制 Buffer -> 可以直接把这样的数据返回给前端(图片只能返回二进制,返回字符串将使图片失效)
console.log(data.toString());
} })

2.数据交互 - get和post和文件上传

  • get数据:url里面、小于32K
  • post数据:作为body、比较大
  • file数据:form表单的处理、后端的处理

(1)设置header

  • setHeader()  -->  一般使用这种来设置header(键值对)
  • writeHeader()
  • write()

简单设置header:

 const http=require('http');
const fs=require('fs'); let server=http.createServer(function(req, res){
fs.readFile(`www${req.url}`, function(err, data){
if(err){
// 返回404
res.writeHeader(404); // header
res.write('Not Found'); // body
}else{
res.write(data);
}
res.end();
});
}); server.listen(8080);

(2)get数据处理

get表单:

 <form action="http://localhost:8080/aaa" method="get">
用户:<input type="text" name="user" /><br>
密码:<input type="password" name="pass" /><br>
<input type="submit" value="提交">
</form>

后端node:

 const http=require('http')
const url=require('url') let server=http.createServer(function(req, res){
let {pathname, query} = url.parse(req.url, true)
console.log(pathname) // -> /xxx的形式
console.log(query) // -> { user: 'xxx', pass: 'xxx' }的形式 res.end()
}) server.listen(8080)

 

(3)post数据处理

post表单(注意get和post请求可以同时提交):

 <form action="http://localhost:8080/aaa?id=12&a=55" method="post">
用户:<input type="text" name="user" /><br>
密码:<input type="password" name="pass" /><br>
<input type="submit" value="提交">
</form>

后端node:

 const http=require('http')
const querystring=require('querystring') let server=http.createServer(function(req, res){
let str='' // 有一个段到达了
req.on('data', function(data){
str+=data
}) // 结束了
req.on('end', function(){
let post=querystring.parse(str)
console.log(str)
console.log(post)
}) res.end()
}) server.listen(8080)

注意:url和querystring的不同之处:

 1 // url解析整个url
2 url.parse("www.xxx.com/aaa/bbb?a=12&b=5")
3 url.parse("/aaa/bbb?a=12&b=5")
4 // 另外加上true表示进一步解析query参数(不加就默认不进一步解析query):
5 url.parse("/aaa/bbb?a=12&b=5", true)
6 ->
7 {
8   、、、
9   "query": {a: 12, b: 5}
10   、、、
11 }
12
13 // querystring解析数据
14 querystring.parse("a=12&b=5")

(4)get和post数据一块处理

前端还是使用前面的get表单和post表单

后端node:

 const http=require('http');
const url=require('url');
const querystring=require('querystring'); let server=http.createServer((req, res)=>{
// GET
let {pathname, query}=url.parse(req.url, true); // POST
let str='';
req.on('data', function(data){
str+=data;
});
req.on('end', function(){
let post=querystring.parse(str); console.log(pathname, query, post);
}); res.end()
}); server.listen(8080);

注意:在一个表单中可以get请求可以和post请求同时发

(5)文件上传

前端代码:

 <form action="" method="post" enctype="multipart/form-data">
<input type="file" name="upload-file">
<input type="submit" value="上传文件">
</form> 注意:
上传文件时表单中的enctype="multipart/form-data"必须要写
input(file)必须要有name

后端可以使用fs中的readFile和writeFile实现(读取完上传的文件后保存)

这样做有弊端:

  • 只能等到所有数据都到达了才开始处理
  • readFile先把所有数据全读到内存中,然后回调:
  • 1.极其占用内存
  • 2.资源利用极其不充分

更好的方法:使用流,实例见后面的文件上传实例

3.数据交互实例 - 登陆注册简单实现

(1)基本原理

 // GET数据 -> 在url中
let {pathname, query} = url.parse(req.url, true) // 请求的地址及?之后的参数 // POST数据 -> 在body里 比较大
let str = ''
req.on('data', function(data){
str += data // post提交的数据
}) req.end('end', function(err){
let post = querystring.parse(str) // 解析提交的数据(字符串->对象)
})

(2)前端代码

 <!-- author: wyb -->
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>登陆</title>
<script src="https://cdn.bootcss.com/jquery/3.2.1/jquery.min.js"></script>
</head>
<body> 用户名: <input type="text" id="user"> <br>
密码: <input type="password" id="pass"> <br>
<input type="button" value="注册" id="btn1">
<input type="button" value="登陆" id="btn2"> <script>
/*
// 前后端接口:
用户注册:
/reg?user=xxx&pass=xxx
=>{error: 0, msg: '说明'} 用户登陆:
/login?user=xxx&pass=xxx
=>{error: 0, msg: '说明'}
*/
$(function () {
// 注册
$('#btn1').click(function () {
$.ajax({
url: '/reg',
data: {user: $('#user').val(), pass: $('#pass').val()},
dataType: 'json',
success(data){
if(data.error){
alert("错了: " + data.msg)
} else {
alert("注册成功")
}
},
error(){
alert("错了")
}
})
}) // 登陆
$('#btn2').click(function () {
$.ajax({
url: '/login',
data: {user: $('#user').val(), pass: $('#pass').val()},
dataType: 'json',
success(data){
if(data.error){
alert("错了: " + data.msg)
} else {
alert("登陆成功")
}
},
error(){
alert("错了")
}
})
})
})
</script> </body>
</html>

(3)后端代码(node)

 const http = require('http');
const url = require('url');
const querystring = require('querystring');
const fs = require('fs'); /*
// 前后端接口:
用户注册:
/reg?user=xxx&pass=xxx
=>{error: 0, msg: '说明'} 用户登陆:
/login?user=xxx&pass=xxx
=>{error: 0, msg: '说明'}
*/ // users在内存中保存用户登陆信息
let users = {
// 'xxx': '123456',
// 'wyb': '654321'
}; let server = http.createServer(function(req, res) {
// GET
let {pathname, query} = url.parse(req.url, true); // POST
let str = '';
req.on('data', function (data) {
str += data;
}); req.on('end', function () {
let post = querystring.parse(str);
let {user, pass} = query switch (pathname) {
// 注册
case '/reg':
if (!user) {
res.write('{"error": 1, "msg": "user is required!"}')
} else if (!pass) {
res.write('{"error": 1, "msg": "pass is required!"}')
} else if (!/^\w{3,32}$/.test(user)) {
res.write('{"error": 1, "msg": "invalid username!"}')
} else if (!/^\w{6,32}$/.test(pass)) {
res.write('{"error": 1, "msg": "invalid password!"}')
} else if (/^['"|]$/.test(pass)) {
res.write('{"error": 1, "msg": "invalid password!"}')
} else if (users[user]) {
res.write('{"error": 1, "msg": "username already exists!"}')
} else {
users[user] = pass
res.write('{"error": 0, "msg": "register success!"}')
} res.end()
break
// 登陆
case '/login':
if (!user) {
res.write('{"error": 1, "msg": "user is required!"}')
} else if (!pass) {
res.write('{"error": 1, "msg": "pass is required!"}')
} else if (!users[user]) {
res.write('{"error": 1, "msg": "no this user!"}')
} else if (users[user]!==pass) {
res.write('{"error": 1, "msg": "username or password is incorrect!"}')
} else {
res.write('{"error": 0, "msg": "login success!"}')
} res.end()
break
default:
fs.readFile(`www${pathname}`, function (err, data) {
if (err) {
res.writeHead(404)
res.write("Not Found!")
} else {
res.write(data)
} res.end()
})
} }); }); server.listen(8080);

4.文件上传实例 - 用流实现

直接看这里:https://www.cnblogs.com/wyb666/p/9694481.html

node.js入门基础的更多相关文章

  1. Node.js 入门:Express + Mongoose 基础使用

    前言 Express 是基于 Node.js 平台的 web 应用开发框架,在学习了 Node.js 的基础知识后,可以使用 Express 框架来搭建一个 web 应用,实现对数据库的增删查改. 数 ...

  2. 极简 Node.js 入门 - Node.js 是什么、性能有优势?

    极简 Node.js 入门系列教程:https://www.yuque.com/sunluyong/node 本文更佳阅读体验:https://www.yuque.com/sunluyong/node ...

  3. 极简 Node.js 入门 - 2.1 Path

    极简 Node.js 入门系列教程:https://www.yuque.com/sunluyong/node 本文更佳阅读体验:https://www.yuque.com/sunluyong/node ...

  4. 极简 Node.js 入门 - 4.4 可写流

    极简 Node.js 入门系列教程:https://www.yuque.com/sunluyong/node 本文更佳阅读体验:https://www.yuque.com/sunluyong/node ...

  5. 极简 Node.js 入门 - 5.2 url & querystring

    极简 Node.js 入门系列教程:https://www.yuque.com/sunluyong/node 本文更佳阅读体验:https://www.yuque.com/sunluyong/node ...

  6. node.js学习(二)--Node.js控制台(REPL)&&Node.js的基础和语法

    1.1.2 Node.js控制台(REPL) Node.js也有自己的虚拟的运行环境:REPL. 我们可以使用它来执行任何的Node.js或者javascript代码.还可以引入模块和使用文件系统. ...

  7. Node.js系列基础学习----安装,实现Hello World, REPL

    Node.js基础学习 简介 简单的说 Node.js 就是运行在服务端的 JavaScript.Node.js 是一个基于Chrome JavaScript 运行时建立的一个平台.Node.js是一 ...

  8. Node.js 入门手册:那些最流行的 Web 开发框架

    这篇文章与大家分享最流行的 Node.js Web 开发框架.Node 是一个服务器端 JavaScript 解释器,它将改变服务器应该如何工作的概念.它的目标是帮助程序员构建高度可伸缩的应用程序,编 ...

  9. 【特别推荐】Node.js 入门教程和学习资源汇总

    这篇文章与大家分享一批很有用的 Node.js 入门教程和学习资源.Node 是一个服务器端的 JavaScript 解释器,它将改变服务器应该如何工作的概念.它的目标是帮助程序员构建高度可伸缩的应用 ...

随机推荐

  1. C 枚举 相同的值

    /********************************************************************************* * C 枚举 相同的值 * 说明: ...

  2. [LeetCode&Python] Problem 693. Binary Number with Alternating Bits

    Given a positive integer, check whether it has alternating bits: namely, if two adjacent bits will a ...

  3. sourceinsight - imsoft.cnblogs

    显示空格的问题,options->document options->visible space 前面的对勾去掉就好了 sourceinsight中文显示乱码问题彻底解决办法:http:/ ...

  4. 51Nod:1268 和为K的组合

    1268 和为K的组合  基准时间限制:1 秒 空间限制:131072 KB 分值: 20 难度:3级算法题  收藏  关注 给出N个正整数组成的数组A,求能否从中选出若干个,使他们的和为K.如果可以 ...

  5. 【转】Python判断字符串是否为字母或者数字

    str_1 = " str_2 = "Abc" str_3 = "123Abc" #用isdigit函数判断是否数字 print(str_1.isdi ...

  6. benthos stream 处理工具说明

    benthos 是golang 编写的流处理工具,同时也可以作为一个类库使用,当前支持的source sink 还是比较全的 (kafka rabbitmq http service s3 redis ...

  7. streamsets k8s 部署试用

    使用k8s 进行 streamsets的部署(没有使用持久化存储) k8s deploy yaml 文件 deploy.yaml apiVersion: extensions/v1beta1 kind ...

  8. wcat 进行iis 压力测试

    如何建立起WCAT Microsoft的Web容量分析工具(WCAT) 是测试你的客户-服务器网络配置的必备工具.这个工具在你的网络上对多种工作量的场景进行仿真,允许你确定你的网络和服务器的最佳配置. ...

  9. Cygwin安装与使用入门

    版权声明:本文为博主原创文章,未经博主同意不得转载. https://blog.csdn.net/canlets/article/details/28646115 对于 UNIX 本身,也有各种称呼. ...

  10. MySQL命令行--导入导出数据库

    MySQL命令行导出数据库:   1,进入MySQL目录下的bin文件夹:cd MySQL中到bin文件夹的目录 如我输入的命令行:cd C:\Program Files\MySQL\MySQL Se ...