关于前端:关于node

NodeJs简介

NodeJs是一个JavaScript运行环境,它让JavaScript能够开发后端程序,简直能实现其它后端语言能实现的所有性能。是一个基于 Chrome V8 引擎的 JavaScript 运行时
NodeJs善于解决高并发。它不会为每个客户连贯创立一个新的线程,而仅仅应用一个线程。当有用户连贯了,就会触发一个外部事件,通过非阻塞I/O,事件驱动机制,让NodeJs程序宏观上也是并行的

对于过程和线程:
过程:负责为程序的运行提供必备的环境。相当于工厂中的车间
线程:计算机中的最小计算单位,线程负责执行过程中的程序。相当于工厂中车间的工人
JS是单线程的

NodeJS文档:http://nodejs.cn/learn

NodeJs的装置

下载地址:http://nodejs.cn/download/
验证NodeJs是否装置胜利:在cmd中输出命令node -v,若显示版本号则装置胜利

命令行窗口(cmd)

相干罕用的命令:
dir:列出当前目录下的所有文件或子目录
cd 目录名:进入到指定的目录
md 目录名:创立一个文件夹
rd 目录名:删除一个文件夹
磁盘名::进入到对应的磁盘
cd ./:示意当前目录
cd ../:示意上一级目录
cd /:返回根文件夹

当咱们在命令行窗口关上一个文件,或调用一个程序时,
零碎会首先在当前目录下寻找文件程序,如果找到了则间接关上
如果没有找到,则会顺次到环境变量中的path的门路中寻找
如果还是没有找到,则会报错

注:咱们能够将一些常常须要拜访的程序好文件的门路增加到path中,这样咱们能够在任意地位来拜访这些文件和程序了

运行NodeJs程序

在cmd(或者编译软件中内置的控制台)中,进入到对应的要运行的文件夹,而后输出命令:node 要执行的文件名
要运行谁,就node谁

NodeJs自启动工具

supervisor / nodemon(集体举荐) /...:可能不停地监听NodeJs的文件,进行实时批改
supervisor的装置:npm install -g supervisor
nodemon的装置:npm install -g nodemon (官网:https://nodemon.io/)

应用:
可用supervisor/nodemon来代替node命令:supervisor/nodemon 要执行的文件名

NodeJs中的一些输入命令

console.log('...') //一般输入语句
console.dir('...') //显示一个对象所有的属性和办法,残缺的显示出对象(在相似json的树中打印元素)
console.error('...')  //正告输入
console.time(标识)  //计时开始
console.timeEnd(标识)  //计时完结
console.assert(表达式,输入文字)  //当表达式为假时,输入文字(抛出谬误),否则不输入文字

对于npm,包

包(package):CommonJS的包标准由包构造和包形容文件两个局部组成
包构造:用于组织包中的各种文件
包构造实际上是一个压缩文件,其中蕴含以下的一些文件:
pachage.json:形容文件(必须的)
bin:可执行二进制文件
lib:js代码
doc:文档
test:单元测试
包形容文件:形容包的相干信息,表白非代码的相干信息,以供内部读取剖析(json格局的文件--package.json)
创立package.json文件的命令:npm init(须要手动抉择)/npm init -y(默认全副yes)
package.json的罕用属性:
name:项目名称
version:版本号
description:我的项目形容
main:主模块
dependencies:依赖包列表
devDependencies:开发时的依赖
scripts:脚本(可应用npm命令执行)
license:开源协定

新版的nodejs曾经集成了npm,所以装置node的同时,npm也一起装置好了
对于node而言,npm帮忙其实现了第三方模块的公布,装置和依赖等

npm相干命令:
npm -v:查看npm版本
npm version:查看所有模块的版本
npm search 包名:搜寻模块包
npm install 包名:在当前目录安装包
npm install 包名@版本号:在当前目录装置对应版本的包
npm install 包名 -g:全局模式安装包
npm install 包名 --save:安装包并增加到依赖中(npm install会主动下载以后我的项目依赖中的包)
npm install 包名 --save-dev:安装包并增加到开发时依赖列表
npm remove 包名:删除包
npm uninstall 包名:卸载包
npm view 包名:查看包
npm install 文件门路:从本地装置
npm install 包名 -registry=地址:从镜像源装置
npm config set registry 地址:设置镜像源
npm update 包/模块名:更新包/模块
npm cache clear:清空npm本地缓存

从npm装置的 包/模块 都会放到node_modules文件夹中(上传我的项目时不会把node_modules都上传)

node在应用模块名字来引入模块时,他会首先在当前目录的node_modules中寻找是否含有该模块,
如果有则间接应用,如果没有则间接去上一级目录的node_modules中寻找,直到找到为止,
若直到找到磁盘的根目录仍然没有,则报错

有时候对于一些大的包,用npm装置下载会很慢,能够利用cnpm来装置下载
装置cnpm:npm install -g cnpm --registry=https://registry.npm.taobao.org

若在npm安装包时,总是提醒npm resource busy or locked...的报错,
解决办法:npm cache clean
          npm install

npm官网:https://www.npmjs.com/

NodeJs作用域

NodeJs中一个文件就是一个模块
模块中应用var定义的变量为部分作用域,只能在该模块中应用。因为模块在应用时会把NodeJs编译为一个函数,那么应用var的定义的变量,天经地义只能在这个模块(函数)中应用
如:
在某个模块中编写了var a=100;
NodeJs在执行前,编译这个模块为:
function(exports,require,module,__filename,__dirname){
    var a=100;
}

全局对象:global.属性/办法(相似于window)
global.name='xxx'(应用时global关键字可省略不写)

NodeJs的模块化

NodeJs采纳模块形式治理和组织代码,NodeJs所有的性能都存在每个模块中

一个具备特定性能的文件就是一个模块,模块间可能存在肯定的依赖关系,应用模块能够很好地把这些依赖关系整合起来

模块标准:
AMD:异步模块定义,异步的加载模块,requirejs利用了这一标准,适宜客户端浏览器环境
CMD:是seajs推崇的标准(相当于AMD和CommonJs的联合再加上其余货色)
CommonJs:NodeJs采纳了此标准来定义模块,但其采纳的是同步加载文件形式,只实用于服务端

exports导出(裸露)对象:因为nodejs是基于模块化治理,所有用户编写的代码都是部分的,要与其它模块共享数据能够应用裸露对象
module模块对象:module.exports(真正的裸露对象)
若要对外裸露属性或办法,就用exports就行(exports只能应用.的形式来向外裸露外部变量)
若要裸露对象(如class,蕴含了很多属性和办法),就用module.exports(module.exports能够通过.的形式,也能够间接赋值)
require函数:引入(加载)模块
require办法的外部加载十分复杂,其加载的优先级也各不相同,如下图:


NodeJs的模块分类:
自定义模块:咱们本人编写的模块
第三方模块:第三方开发者奉献的模块(npm install 包名)
零碎(内置)模块:NodeJs官网开发的模块
以上模块可用require函数引入:var xxx=require('xxx')(若为外围模块(零碎的),则xxx为模块名,若为文件模块(用户自定义的),则xxx为绝对应的模块相对路径(./不能省略))

实际上模块中的代码都是包装在一个函数中执行的,并且在函数执行时,同时传递了5个实参:
exports:该对象用来将变量或函数裸露到内部
require:函数,用来引入内部的模块
module:代表的是以后模块自身,exports是module的属性
__filename:以后模块文件的残缺门路
__dirname:以后模块所在文件夹的残缺门路

内置模块—HTTP模块

HTTP协定:
网络是信息传输,接管,共享的虚构平台
网络传输数据有肯定规定,即称为协定。HTTP协定就是其中一种,也是应用最频繁的一种
HTTP协定是TCP/IP协定之上的一个应用层协定,用于定义WEB浏览器与WEB服务器之间替换数据的过程及数据自身的格局。采纳的是 申请/应答 形式来传递数据(一次申请对应一次应答)

HTTP模块是基于HTTP协定的通信模块,可用于创立HTTP服务器,也可作为客户端向其余服务器发动申请

引入HTTP模块:var http=require('http')
HTTP模块中的某些办法:(更多办法可查看文档)
HTTP服务端的办法:
1. http.createServer([options][, requestListener]):创立Web服务
   http.createServer((req, res) => {  //req获取url(客户端)传过来的信息,res给浏览器响应信息
    //应用此回调解决每个独自的申请
    res.writeHead(200,{"Content-type":"text/html;charset=utf-8"}); //设置响应头(状态码是200,文件类型是html,字符集是utf-8)(设置charset=utf-8可解决中文乱码问题)
    res.write('xxx'); //页面上显示xxx内容
    res.end();  //完结响应
   }).listen(监听的端口号)
   
HTTP客户端的办法:   
1. http.get(url(指标地址)[, options][, callback]) / http.get(options[, callback]): 模拟客户端从服务端获取数据(将申请办法设为GET申请)
   它将申请办法设置为 GET 并且会主动调用req.end()
   callback调用时只有一个参数:res(返回对象,接管到服务器响应的所有内容)
   var request=http.get({host:'localhost',path:'/user?name=helios&age=22',port:3000},
                        function(res){
                                    res.setEncoding('utf-8');
                                    res.on('data',function(data){
                                        console.log(' 服务端相应回来的数据为:'+data);
                                    })
                        });
2.  http.request(url(指标地址)[, options][, callback]) / http.request(options[, callback]):发动http申请
    callback调用时只有一个参数:res
    var req  =  http.request(options,(res)=>{
        res.setEncoding('utf-8');
        res.on('data',(data)=>{
            console.log(data);
        });
    });
    

内置模块—fs模块

文件系统模块,用于对操作系统中的文件进行相干操作
常见的操作有:读文件,写文件,删除文件等

引入fs模块:var fs=require('fs')

读文件:
间接读取(将硬盘上的所有内容全副读入内存后才触发回调函数)和流读取(将数据从硬盘中读取一节就触发回调函数,实现大文件操作)
间接读取:同步读取(fs.readFileSync('xxx(文件名))
         异步读取(fs.readFile('xxx(文件名)',function(err,txt){...}))

写文件:
引入fs模块后,找到要写入的内容,开始写入
异步写文件:fs.writeFile()
fs.writeFile('xxx(文件名)',data(写入的数据),function(err){...})
同步写文件:fs.writeFileSync()
fs.writeFileSync('xxx(文件名)',data(写入的数据))

删除文件:
fs.unlink('xxx(文件名)',function(err){...})
fs.unlinkSync('xxx(文件名)')

删除非空目录:
1. 读取目录中的文件及文件夹列表:fs.readdir();
2. 读取每一个文件的详细信息:fs.stat();
3. 判断如果是文件,则间接删除:fs.unlink();
4. 若如果是目录,则递归调用本人
5. 删除底下的空目录:fs.rmdir();
具体实现(同步形式):
const fs=require("fs");
function deldir(path) {
    let files = [];
    if( fs.existsSync(path) ) {  //先查看是否有含此门路的目录
        files = fs.readdirSync(path);  //读取目录中的文件及文件夹列表
        files.forEach(function(f,i){
            let curPath = path + "/" + f;
            if(fs.statSync(curPath).isFile()) {  //若是文件,则间接删除
                fs.unlinkSync(curPath);
            } else {   //若是目录则调用本身函数进行递归
                deldir(curPath);
            }
        });
        //删除空目录
        fs.rmdirSync(path);
    }
}
deldir('xxx(要删除的目录)');

读取文件信息:
fs.stat('文件名',function(err,state){
        /*
          state是文件的信息对象
          蕴含罕用的文件信息:
          size:文体大小,字节
          mtime:文件批改工夫
          birthtime:文件创建工夫
          ...
          
          蕴含的一些办法:
          .isFile():判断以后查看的对象是不是一个文件
          .isDirectory():判断以后查看的对象是不是一个目录(文件夹)
          ...
        */
})  

测验门路是否存在:
fs.existsSync(path)

读取一个目录的目录构造:
fs.readdir(path[,options],function(err,files){...});  //files是一个字符串数组,每个元素就是一个文件夹或文件的名字
fs.readdirSync(path[,options]);

截断文件(将文件批改为指定大小):
fs.truncate(path,len,callback);
fs.truncateSync(path,len);

创立目录:
fs.mkdir(path[,mode],callback);
fs.mkdirSync(path[,mode]);

删除(空)目录:
fs.rmdir(path,callback);
fs.rmdirSync(path);

重命名文件和目录:
fs.rename(oldpath,newpath,callback);
fs.renameSync(oldpath,newpath);

监督文件更改写入:
fs.watchFile(filename[,options],listener(curr,prev));  //listener为回调函数,当文件发生变化时,回调函数会执行(参数:curr为以后文件状态,prev为批改前文件的状态)

追加文件内容:
fs.appendFile('文件名','追加的内容',(err)=>{...})

创立文件并笼罩写入内容:
fs.writeFile('文件名','内容',(err)=>{...})


流:
一组有序的,有终点和起点的字节数据的传输方式
在应用程序中各种对象之间替换与传输数据时,总是将该对象中所蕴含的数据转换为各种模式的流数据(字节数据),在通过流的传输,达到目标对象后再将流数据转换为该对象中可应用的数据

四种流类型:Readable(可读),Writable(可写),Duplex(可读可写),Transform(操作被写入数据,而后读出后果)
解决流事件:data(有数据可读时触发),end(没有更多的数据可读时触发),error(在接管和写入过程中产生谬误时触发),finish(所有数据已被写入到底层零碎时触发)

读取文件流:
var readerStream=fs.createReadStream('xxx(文件名)');  //创立可读流
readerStream.on('data',function(chunk){   //监听data事件,有数据读取进去就会触发,接管到数据
                    ...
              });
readerStream.on('end',function(){});  //监听end事件,当文件读取结束时,触发该事件
readerStream.on('error',function(){});  //监听error事件,当文件读取出错时,触发该事件
解决从流中读取数据中文乱码的问题:加上readerStream.setEncoding("UTF8");

写入文件流:
var writerStream=fs.createWriteStream('xxx(文件名)');  //创立可写流
writerStream.write('xxxx(写入的内容)',["UTF8"]);  //写入流
writerStream.end();  //写完当前完结
writerStream.on('finish',function(){...});  //绑定一个finish事件来表明写入胜利
writerStream.on('error',function(){});  //监听error事件,当文件读取出错时,触发该事件


管道(pipe):
提供了一个输入流到输出流的机制。通常咱们用于从一个流中获取数据并将数据传递到另一个流中,这样能够缓缓实现大文件的复制过程(输入流.pipe(输出流))
具体实现:
//创立一个可读流
var readerStream=fs.createReadStream('xxx(文件名)'); 
//创立一个可写流
var writerStream=fs.createWriteStream('xxxx(文件名)'); 
//管道读写操作
readerStream.pipe(writerStream);


链式流:
通过连贯输入流到另外一个流并创立多个流操作链的机制
链式个别用于管道操作
可用管道和链式来压缩和解压文件
压缩文件:(将xxx文件压缩为xxx.gz)
var fs=require('fs');
var zlib=require('zlib');
fs.createReadStream('xxx(文件名)').pipe(zlib.createGzip()).pipe(fs.createWriteStream('xxx.gz'));
解压文件:(将xxx.gz解压为xxx文件)
var fs=require('fs');
var zlib=require('zlib');
fs.createReadStream('xxx.gz').pipe(zlib.createGunzip()).pipe(fs.createWriteStream('xxx(文件名)'));

内置模块—path模块

可用来解决与转换文件门路
用于格式化或拼接一个残缺的门路

引入path模块:var path=require('path');

path上的办法:
较不太罕用的:
path.normalize(p);  //规范化门路(留神./和../)
path.join(path1,path2,...);  //用于连贯门路,该办法的主要用途是会正确应用以后零碎的门路分隔符(Unix零碎是'/',Windows零碎是'\')
path.resolve([from...],to);  //将to参数解析为绝对路径。取得相对路径的绝对路径计算(会应用第一个参数作为第二个参数的基准)
path.isAbsolute(path);  //判断path是否为绝对路径
path.relative(from,to);  //将门路转为相对路径
path.dirname(path);  //返回门路中代表文件夹的局部
path.basename(path[,ext]);  //返回门路中的最初一部分 
path.extname(path);  //返回门路中文件的后缀名(即门路中最初一个'.'之后的局部),若门路中并不蕴含'.'或该门路中只蕴含一个'.',且这个'.'为门路的第一个字符,则此命令返回空字符串
较为罕用的:
path.parse(pathString);  //返回门路字符串的对象
path.format(pathObject);  //从对象中返回门路字符串

内置模块—url模块

url:寰球对立资源定位符,对网站资源的一种简洁表达形式,也称为网址

引入url模块:var path=require('url');

url被解析时,会返回一个url对象,它蕴含每个组成部分作为属性
url的形成(从左到右):
1. 残缺构造
协定://用户名:明码@主机名.名.域:端口号/目录名/文件名.扩展名?参数名1=参数值1&参数名2=参数值2&...#hash
2. http协定的URL常见构造
协定://主机名.名.域/目录名/文件名.扩展名?参数名1=参数值1&参数名2=参数值2&...#hash

提供了两套对于url进行解决的API性能:
1. 旧的node.js url模块
   应用传统的 API 解析 URL 字符串:
   const xxx=url.parse('https://user:pass@sub.host.com:8080/p/a/t/h?query=string#hash');
    
2. 新的url模块(WHATWG URL规范模块)
   WHATWG的URL接口:
   应用 WHATWG 的 API 解析 URL 字符串:
   const xxx=new url.URL('https://user:pass@sub.host.com:8080/p/a/t/h?query=string#hash');
   属性:
   xxx.hash:获取及设置URL的分段(hash)局部
   xxx.host:获取及设置URL的主机(host)局部
   xxx.hostname:获取及设置URL的主机名(hostname)局部
   xxx.href:获取及设置序列化的URL
   xxx.origin:获取只读序列化的URL origin局部
   xxx.pathname:获取及设置URL的门路(path)局部
   xxx.search:获取及设置URL的序列化查问(query)局部
   

内置模块—Query String模块

用于解决query(参数)字符串
模块提供用于解析和格式化 URL 查问字符串的实用工具

引入Query String模块:var qs=require('querystring');

将query字符串变成query对象:
qs.parse(str)  //qs.decode()是此办法的别名
还可依据某个符号进行切分键值对和键值:
qs.parse(str,'先依据什么符号来切分键值对','再依据什么符号来切分键和值')
e.g.
let str='name-aa#pass-123#sex-0';
let obj=qs.parse(str,'#','-');
输入obj的后果为:{name:'aa',pass:'123',sex:'0'}

将query对象变成query字符串:
qs.stringfy(obj);  //qs.encode()是此办法的别名
还可依据某个符号进行切分键值对和键值:
qs.stringfy(str,'先依据什么符号来切分键值对','再依据什么符号来切分键和值')
 e.g.
let obj={name:'aa',pass:'123',sex:'0'}
let str=qs.stringfy(obj,'^','?');
输入str的后果为:'name?aa^pass?123^sex?0'

对URL查问字符串的特定要求进行了优化的形式,对给定的str执行URL百分比编码:
qs.escape(str);

在给定的str上执行URL百分比编码字符的解码:
qs.unescape(str);

内置模块—events模块

只提供了一个对象:events.EventEmitter
EventEmitter的外围就是事件触发与事件监听器性能的封装
所有这些产生事件的对象都是event.EventEmitter的实例

引入events模块:var events=require('events');

创立eventEmitter对象:
var eventEmitter=new events.EventEmitter();

单事件监听:
var events=require('events');
var eventEmitter=new events.EventEmitter();
eventEmitter.on('xxx(事件)',function(arg){...});
setTimeout(function(){
    eventEmitter.emit('xxx(对应下面的事件)','参数');  //要调用emit办法对应的事件才会被触发(依照监听器注册的程序,同步地调用每个注册到名为xxx的事件的监听器,并传入提供的参数)
},1000)

多事件监听:
EventEmitter的每个事件都由一个事件名和若干个参数组成。反对若干个事件监听器
当事件触发时,注册到这个事件的事件监听器被顺次调用,事件参数作为回调函数参数传递
var events=require('events');
var eventEmitter=new events.EventEmitter();
eventEmitter.on('xxx(事件)',function(arg){内容1});
 eventEmitter.on('xxx(事件)',function(arg){内容2});
setTimeout(function(){
    eventEmitter.emit('xxx(对应下面的事件)','参数');  //要调用emit办法对应的事件才会被触发(依照监听器注册的程序,同步地调用每个注册到名为xxx的事件的监听器,并传入提供的参数)
},1000)

无关EventEmitter的一些办法:


无关EventEmitter的类办法:

无关EventEmitter的事件:

error事件:
EventEmitter定义了一个非凡事件:error,它蕴含谬误的语义,在遇到一场时通常会触发error事件
当error触发时,EventEmitter规定如果没有响应的监听器,Nodejs会把他当做异样,退出程序并输入错误信息
ar events=require('events');
var eventEmitter=new events.EventEmitter();
eventEmitter.emit('error'); 

继承EventEmitter:
大多数状况下,咱们不会间接应用EventEmitter,而是在对象中继承它
包含fs,net,http在内的,只有是反对事件响应的外围模块都是EventEmitter的子类
这样做的起因:
1. 具备某个实体性能的对象实现事件合乎语义,事件的监听和产生应该是一个对象的办法
2. JavaScript的对象机制是基于原型的,反对局部多重继承,继承EventEmitter不会打乱对象原有的继承关系

第三方模块—nodemailer

一个简略易用的 Node.JS 邮件发送模块(通过 SMTP,sendmail,或者 Amazon SES),反对 unicode

nodemailer的次要特点:
反对Unicode编码
反对Window零碎环境
反对HTML内容和一般文本内容
反对附件(传送大附件)
反对HTML内容中嵌入图片
反对SSL/STARTTLS平安的邮件发送
反对内置的transport办法和其余插件实现的transport办法
反对自定义插件解决音讯
反对XOAUTH2登录验证

利用场景:注册案例(发送邮箱验证码)

nodemailer的官网:
https://nodemailer.com/about/

nodemailer的装置:
npm install nodemailer

nodemailer的应用:
"use strict";
const nodemailer = require("nodemailer");
//当您没有真正的邮件帐户进行测试时才须要创立测试账户
let testAccount = await nodemailer.createTestAccount();
//创立发送邮件的对象(若是大型企业的发送方,可通过此模块下的文件夹lib/well-know/service.json查找对应企业的相干信息)
let transporter = nodemailer.createTransport({
    host: "smtp.ethereal.email",  //发送方的邮箱smtp
    port: 587,  //端口号
    secure: false, // true for 465(port), false for other ports
    auth: {
  user: testAccount.user, // 发送方的邮箱地址
  pass: testAccount.pass, // mtp验证码
},
});

//邮件的相干信息
let mailObj={
    from: '"Fred Foo" <foo@example.com>', // 发送方邮箱
    to: "bar@example.com, baz@example.com", // 接管方邮箱
    subject: "Hello", // 邮件题目
    text: "Hello world?", // 邮件文本信息
    html: "<b>Hello world?</b>", // 邮件的html显示局部(和text局部两者只能抉择一个)
};

//发送邮件
let info = await transporter.sendMail(mailObj,(err,data)=>{
      ...
});

在qq邮箱中设置SMTP服务:
qq邮箱首页 --> 账户 --> POP3/IMAP/SMTP/Exchange/CardDAV/CalDAV服务 (点击对应的SMTP服务开启即可)

缓存区Buffer

像一个数组,专门用来存储二进制数据,它的元素显示为16进制的两位数(实际上一个元素就示意内存中的一个字节(8bit))
Buffer中的内存不是通过JavaScript调配的,而是在底层通过C++申请的
能够间接通过Buffer来创立内存空间
Buffer的大小一旦确定,则不能被批改

创立一个指定大小的Buffer:
1. var buf=new Buffer(xx) / var buf=new Buffer([...])(按指定数组创立缓存区); (buffer构造函数是不举荐应用的)
2. var buf=Buffer.alloc(xx); (罕用)
3. var buf=Buffer.allocUnsafe(xx);  (buffer中可能含有敏感数据)

通过索引来批改操作buf中的元素:
buf[x]=xxx

通过索引来查看buf中的元素:
buf[x]

将一个字符串str转换为buffer:
Buffer.from(str)

将一个buffer中的数据转换为字符串显示进去:
buf.toString()

写入内容到缓存区:
buf.write('xxx')

缓存区的拷贝(复制):
buf1.copy(buf2)  //buf1复制给buf2

NodeJs REPL(交互式解释器)

"读取-求值-输入"循环(Read-Eval-Print Loop),是一个简略的,交互式的编程环境
Node自带交互式解释器,可执行以下工作:
读取:读取用户输出,解析输出了Javascript数据结构并存储再内存中
执行:执行输出的数据结构
打印:输入后果
循环:循环操作以上步骤直到用户两次按下ctrl c按钮退出

在cmd中输出命令node启动Node终端,即可在>后输出简略的表达式,并按下回车来计算结果 

简略的表达式运算:
xx+xx,xx-xx,xx*xx,xx/xx,xx+(xx+xx)/xx,...

多行表达式:
如执行循环:

三个点的符号是回车换行后零碎主动生成的(Node会自动检测是否为间断的表达式)

应用变量:
能够将数据存储在变量中,并在你须要的时候应用它
变量申明须要应用var关键字,如果没有应用var关键字变量会间接打印进去。应用var关键字的变量能够应用console.log()来输入变量

下划线变量:
能够应用下划线获取上一个表达式的运算后果

REPL的一些相干命令:
ctrl+c:退出以后终端
ctrl+c按下两次:退出Node REPL
ctrl+d:退出Node REPL
向上/下:查看输出的历史命令
tab键:列出以后命令
.help:列出应用命令
.break/.clear:退出多行表达式
.save filename:保留以后的Node REPL会话到指定文件
.load filename:载入以后的Node REPL会话的文件内容

NodeJs 回调函数

Nodejs异步编程的间接体现就是回调
回调函数,又称为回调。将a函数作为参数传入b函数中,b函数执行过程中依据机会或条件决定是否调用a函数,a函数就是回调函数
在执行代码时没有阻塞或期待文件I/O操作,这就大大提高了Nodejs的性能,能够解决大量的并发申请
回调函数个别作为函数的最初一个参数呈现

阻塞代码:(同步)
var fs=require('fs');
var data=fs.readFileSync('xxx');
console.log(data.toString());
console.log('程序执行结束');

非阻塞代码:(异步)
var fs=require('fs');
fs.readFile('xxx',(err,data)=>{                     
        if(err){
            return console.error(error);
        }
        console.log(data.toString())
});
console.log('程序执行结束');

回调函数原理:
以setinterval(show,1000)为例:

回调函数的用处:
注册事件,异步函数,...
通常用于达到某个机会或条件时须要执行代码的状况,就应用回调函数


同步与异步:
同步:一个工作期待前一个工作完结,而后再执行,程序的执行程序与工作的排列程序是统一的,同步的
情景:张三去买奶茶,前面排队的是李四。
      张三:给我来一杯卡布奇诺
      服务员:没有卡布奇诺了
      张三:啊,那我打电话问一下敌人看看他还要喝啥
      此时服务员和李四都在等张三
      随后张三打完电话,就对服务员说来一杯百香果吧
      张三买完后,就轮到李四去买了
代码:console.log('1');
      console.log('2');
      for(var i=0;i<1000;i++){...}
      console.log('3');
      (先循环完后再输入3)
异步:每一个工作有一个或多个回调函数,前一个工作完结后,不是执行后一个工作,而是执行回调函数,后一个工作则不等前一个工作完结就执行。所以程序的执行程序与工作的排列程序是不统一的,异步的
情景:张三去买奶茶,前面排队的是李四。
      张三:给我来一杯卡布奇诺
      服务员:没有卡布奇诺了
      张三:啊,那我打电话问一下敌人看看他还要喝啥
      此时张三到队列的旁边打电话等着
      随后就到李四买奶茶
      李四买完后,此时张三就打完电话问敌人,就对服务员说那给我来一杯百香果吧
代码:console.log('1');
      console.log('2');
      setTimeout(function(){
        for(var i=0;i<1000;i++){...}
      },1000);
      console.log('3');
     (在这1s内,先输入3,1s后再循环)
     
Nodejs中共有三种异步实现形式:
回调函数(回调函数不肯定是异步,但异步肯定是回调函数)
事件(基于回调):事件源.on('事件名称',回调函数)
Promise(es6):因为异步的返回后果工夫程序不可控,所以须要应用promise来对立管制输入后果


事件循环驱动
Nodejs单线程相似进入一个while(true)的事件循环,直到没有事件观察者退出,每个异步事件都生成一个事件观察者,如果有事件产生就调用该回调函数

Nodejs应用事件驱动模型,当web server接管到申请,就把它敞开而后进行解决,而后去服务下一个web申请
当这个申请实现,它被放回解决队列,当达到队列结尾,这个后果被传递给用户
这个模型十分高效,可扩展性十分强,因为web server始终承受申请而不期待任何读写操作
(以上可称为非阻塞式I/O或事件驱动I/O)
在事件驱动模型中,会生成一个主循环来监听事件,当检测到事件时触发回调函数。事件相当于一个主体,而所有注册到这个事件上的处理函数相当于观察者

实现繁难爬虫(http模块,…)

网络爬虫:是一种依照肯定的规定,主动地抓取万维网信息的程序或者脚本

可参考的相干步骤:
1. 发动申请获取指标网站:http.get
2. 读取并剖析网站内容(html):可利用cherrio模块 cherrio模块可应用jq的选择器
3. 获取无效信息(可利用正则表达式),下载(可利用管道实现)或其余操作


有下载图片操作的:

网页模块

动态网页:随着html代码的生成,页面内容和显示成果就根本不会发生变化了,除非你批改页面代码
动静网页:页面代码尽管没有变,但显示的内容能够随着工夫,环境或者数据库操作的后果再产生扭转

应用动静网页模板:
模板:将一些固定的构造或体现间接以动态文件模式存储,将须要体现成动态数据的中央用模板语法进行编写,再用模板引擎读取该动态文件,将其余动静的数据替换进去。最终实现产生出一个动静的页面
为避免反复写相干的html代码,可把模板写成一个html文件,而后通过读取文件的形式读取该文件,再通过res.render函数来把相应的数据替换掉,造成一个动静批改数据的页面

对于服务器

服务器的两个概念:硬件服务器(电脑)
                 软件服务器(软件)
服务器要提供HTTP服务,就要装置一个服务器软件
服务器软件:apache,tomcat,iis,ngnix,node,...
服务器ip(确定服务器主机的地位)和端口号(确定服务器里某个程序)
拜访服务器:
1. 关上浏览器
2. 输出网址:172.0.0.1(主机地址)
             localhost(当地主机,本地域名)
             局域网IP(Windows零碎可通过在cmd中输出命令ipconfig查看,Linux/MAC零碎可输出命令ifconfig查看)

局域网:服务器通过网线(无线)连贯,每一个电脑都会有一个ip。(指在某一区域内由多台计算机互联成的计算机组)(不同局域网的IP地址能够反复,不会相互影响)
外网(广域网):是一个遍布全世界的网络。它能够连贯极其大的物理范畴,属于近程性的网络,曾经实现了跨国互联。(是许多的计算机相互之间用线路连贯造成的)(外网IP地址不能反复)

NodeJs开启服务器:(不须要软件)
1. 引入通信模块(http)
2. 创立服务器
3. 监听request事件
4. 监听端口(Windows零碎可通过在cmd输出命令netstat -a查看开启了哪些端口)

express框架

express官网:https://www.expressjs.com.cn/

express特点:
能够设置中间件响应或过滤http申请
能够应用路由实现动静网页,响应不同的http申请
内置反对ejs模板(默认是jade模板)实现模板渲染生成html
本身性能极简,齐全由路由和中间件形成的一个web开发框架

装置express:
npm install express --save

引入express模块:
var express = require('express')

创立express实例:
var app = express();

监听3000端口,开启服务器
app.listen(3000,()=>{  
    console.log('server start');
})


对于req(申请对象)和res(响应对象):
req:申请对象,蕴含了所有客户端申请的数据,申请头,申请主体
res:响应对象,蕴含了所有服务器端发送给客户端的数据,响应头,响应主体

req上的局部办法:
1. req.url:获取到用户申请的网址
2. req.query:获取url上用户传过来的参数(get申请的数据)
3. req.body:接管post申请的数据
4. req.params.参数名:匹配url网址上的数据(在接申请的中央去匹配,再通过语法进行接管)
   e.g. router.get('/xxx/:xx',()=>{res.send('<h1>'+req.params.xx+'</h1>')})
更多req上的办法:(具体可看express官网)

 res上的局部办法:
1. res.writeHead(状态码,响应头对象({"Content-Type":"text/html;charset=utf-8"})):设置响应头
响应头对象蕴含的属性有:Content-Type:响应的文件类型(未指定响应文件类型时,默认是html,编码默认是零碎编码)
                      Content-Length:响应内容的长度(长度是多少就响应多少的内容)
                      Access-Control-Allow-Origin:设置跨域(值为*则为全副网站)
                      ...
                      波及的知识点:MIME类型:可认为是文件类型的表述
                                 常见的MIME类型:.html:text/html
                                                .css:text/css
                                                .js :text/javascript
                                                .png:image/png
                                                .jpg:image/jpeg
                                                .gif:image/gif
                                                .json:text(application)/json
                                                .mp3:audio/mpeg
                                                .mp4:video/mpeg
                                                .pdf:application/pdf
                                                .xml:text/xml
                                                .txt:text/plain
                                                ...
2. res.write("xxx"):把响应的货色xxx返回到页面
3. res.end():完结响应
4. res.send('xxx'):返回任意类型(string,json,...)的数据给客户端(注:若返回的是一个数字类型的,会被当成状态码。此办法只能呈现一次,重复使用会有效和报错)
5. res.status(状态码).send('xxx'):设置状态码并返回数据
6. res.json(data):返回json对象,主动设置响应头。个别针对ajax利用
7. res.render('模板名称',{数据}):读取模板文件并拼接数据,主动将后果发送给浏览器(会在模板的默认目录(views)下依据模板名称找对应的模块)
8. res.download('xxx'):下载当前目录上面的xxx文件
   res.download('xxx','yyy'):下载当前目录上面的xxx文件,并重命名为yyy
9. res.redirect('xxx'):重定向到从指定的url门路xxx
更多res上的办法:(具体可看express官网)


可通过express框架书写api
通过api接口实现数据的申请
api接口形成的因素:ip,port,pathname,methods(get,post),用户传递的数据(数据格式由后端确定)

用get办法写一个api接口:

用post办法写一个api接口:

应用指定的回调函数将HTTP GET申请路由到指定的门路:
app.get('xxx(路由门路,默认为根门路'/')',(req,res)=>{...})
(get申请的数据可间接在网页网址上获取,通过req.query的办法来获取(也可通过软件Postman来进行接口测试))

应用指定的回调函数将HTTP POST申请路由到指定的门路:
app.post('xxx(路由门路,默认为根门路'/')',(req,res)=>{...})
(验证post申请的数据不可间接通过网页网址来获取,在申请体里,通过req.body的办法来获取并用到第三方模块body-parser来进行解析传过来的表单或json或formdata数据。而后可通过软件Postman来进行接口测试)

express—路由

路由:指如何定义利用的断点(URLs)以及如何响应客户的申请(接管用户申请,解决用户数据,返回后果给用户的一套程序)(可了解为生成动静网页的程序)
后端路由的外围:URL

express获取路由实例:
var router=express.Router();

创立对应的路由:
router.申请形式(get/post/all)('/xx(申请地址)',(req,res)=>{...})

可创立一个独立的路由模块供应用:
在routers目录下创立一个独立的文件来编写对应路由:
var express=require('express');
var router=express.Router();
router.get('/xx',function(req,res){...})
module.exports=router;
而后在主文件app.js下引入该文件模块,即可援用对应的路由:
const express=require('express');
const app=express();
let userRouter=require('xxx(下面编写路由的文件门路)')
app.use('/xxx(根门路)',userRouter);  //相当于对应的路由地址为:/xxx/xx...

路由的辨别:
大路由(总路由):app.js 负责承受所有申请,对申请进行调配
小路由(分路由):routes目录下的所有路由模块,只负责解决本人治理的目录下的申请

express—midelware(中间件)

中间件自身是一个函数,位于客户端和路由之间,可拜访申请对象和响应对象,也可调起下一个中间件。相当于拦截器
个别被命名为next的变量
next():执行下一个工作,若不调用则整个申请响应就会停止不会再往后执行

内置中间件:static(动态资源目录):指定一个目录,该目录可被拜访(等同于apache的www)
app.use('/xxx(可加可不加)',express.static('目录的绝对路径'))  

自定义中间件:(要留神next())
全局定义:
app.use('/(若是'/'示意根门路可默认不写)',(req,res,next)=>{
    console.log('中间件');
    let {a}=req.query;
    if(a){
        next();  //是否往下继续执行
    }
    else{
        res.send('短少a');
    }
})
部分定义:
app.get('/user/get',(req,res,next)=>{...},
(req,res)=>{...}
})

第三方中间件(body-parser(解析数据的中间件),multer(上传文件的中间件)等)
利用级中间件绑定到app对象,应用app.use()和app.METHOD(),其中METHOD是须要解决的HTTP申请的办法

定义错误处理中间件:
须要4个参数
app.use((err,req,res,next)=>{
    console.error(err.stack);
    res.status(500).send('xxx');
})

express—模板引擎

views放模板的文件目录:app.set('views','./views');
view engine模板引擎:app.set('view engine','jade/ejs');

ejs模板的局部语法:
<% code %>:用于执行代码
<%= string %>:会进行html本义
<%- string %>:不会本义,原样输入
...
(ejs官网:https://ejs.bootcss.com/#promo)

express—集成数据库

要为express利用增加连贯数据库的能力,只须要加载相应数据库的Node.js驱动即可
可连贯的数据库有:Cassandra,mysql,sql server,mongodb,redis等(具体用法可查看官网)
e.g. 连贯mysql数据库:

express—会话治理Session

会话是一种长久的网络协议,用于实现服务器和客户端间的一些交互行为(可进行身份验证...)
一个会话可能蕴含屡次连贯,每次连贯都被认为是会话的一次操作
HTTP协定是无状态的,自身不反对会话,为了在无状态的HTTP协定上实现会话,就有了Cookie(保留在客户端浏览器中),Session(保留在服务器中)等来存储相干的信息
如果说Cookie机制是通过查看客户身上的"通行证"来确定客户身份的话,那么Session机制就是通过查看服务器上的"客户明细表"来确认客户身份。Session相当于程序在服务器上建设的一份客户档案,客户来访的时候只须要查问客户档案表就能够了
cookie-parser模块和express-session模块配合应用

Cookie和Session的区别:

装置cookie-parser:npm i cookie-parser

装置Session:npm i express-session

cookie-parser模块和express-session模块同时引入:
const cookieParser=require("cookie-parser");
const session=require("express-session");

Session的配置:app.use(session({option}))
option的主要参数:
name:cookie的名字(原属性名为 key)(默认:’connect.sid’)
store:session存储实例
secret:用它来对session cookie签名,避免篡改
cookie:session cookie设置 (默认:{ path: '/',httpOnly:true,secure:false, maxAge:` `null` `})
genid:生成新session ID的函数 (默认应用uid2库)
rolling:在每次申请时强行设置cookie,这将重置cookie过期工夫(默认:false)
resave:强制保留session即便它并没有变动 (默认:true, 倡议设为:false)
proxy:当设置了secure cookies(通过'x-forwarded-proto' header )时信赖反向代理。当设定为true时,'x-forwarded-proto' header 将被应用。当设定为false时,所有headers将被疏忽。当该属性没有被设定时,将应用Express的trust proxy
saveUninitialized:强制将未初始化的session存储。当新建了一个session且未设定属性或值时,它就处于未初始化状态。在设定一个cookie前,这对于登陆验证,加重服务端存储压力,权限管制是有帮忙的(默认:true)
unset:管制req.session是否勾销(例如通过 delete,或者将它的值设置为null)。这能够使session放弃存储状态但疏忽批改或删除的申请(默认:keep)

设置session:req.session.属性名=属性值

获取session:req.session.属性名

从新设置cookie的过期工夫:req.session.cookie.maxAge=xxx

销毁session:req.session.destroy(function(err){...})  (当检测到客户端敞开时调用)

刷新session:req.session.reload()

初始化已有session:req.session.regenerate()

保留session:req.session.save()

Session能够和MongoDB等数据库联合来做长久化的操作:

express—闪存模块

connect-flash(flash)是一个在session中用于存储信息的特定区域
信息写入flash,下一次显示结束后即被革除(只显示一次)
典型的利用是联合重定向的性能,确保信息是提供给下一个被渲染的页面

装置connect-flash模块:var flash=require('connect-flash')

在app.js文件下编写,Express应用这个插: app.use(flash());

利用:

express—express-generator生成器

能够疾速生成一个根本的express开发框架
装置:
npm install express-generator
创立我的项目:
express -e 项目名称  (主动创立我的项目目录)(-e为ejs模板(举荐),若不加则为jade模板)
express -e (手动创立我的项目目录)
装置依赖:
npm i
开启我的项目的形式:
node app(举荐应用,要先在app.js的文件下编写监听相应的端口:app.listen(端口号,callback))
npm start(主动查找当前目录下的package.json文件,找到start对应的命令进行执行)
node ./bin/www
测试项目:
关上浏览器,输出对应的网址

express我的项目生成的文件夹/文件阐明:
bin:可执行文件目录
node_modules:依赖包目录
public:动态文件根目录(搁置所有动态文件:动态html,css,js,图片,字体,视频等)
routers:路由模块目录,动静文件的目录(会优先找动态文件,若没有动态文件则找动静路由,若动静路由也没有,则404)
views:视图目录(寄存所有的页面模板)
app.js:我的项目的主文件,对整个我的项目的所有资源进行兼顾的安顿
package.json:我的项目形容文件,申明我的项目的名称,版本,依赖等信息

以上是对node的局部整顿和总结,心愿有用,有什么倡议欢送提出哦!
大家一起提高~

【腾讯云】轻量 2核2G4M,首年65元

阿里云限时活动-云数据库 RDS MySQL  1核2G配置 1.88/月 速抢

本文由乐趣区整理发布,转载请注明出处,谢谢。

您可能还喜欢...

发表回复

您的电子邮箱地址不会被公开。 必填项已用*标注

此站点使用Akismet来减少垃圾评论。了解我们如何处理您的评论数据