唤醒手腕 - 前端服务器端开发 Node.Js 学习笔记(学习中,更新中)
唤醒手腕 - Node.Js 学习笔记
唤醒手腕个人的学习记录,时间在2021年12月13日 ~ 2021年12月14日,学习方式看官方文档和B站视频,如有错误或者代码问题的地方,欢迎C站大佬能够帮忙指正一下(我是小白,瑟瑟发抖)
官方文档地址:Node.js 官方参考文档
1、Node.Js 基础介绍
Node.js 可以解析JS代码(没有浏览器安全级别的限制)提供很多系统级别的API,文件的读写 (File System),进程的管理 (Process),网络通信 (HTTP/HTTPS)
1.1、网络通信请求
const https = require('http')https.get('http://localhost:8080/index', (res) => {console.log(res) // 返回的是对象let str = ''res.on('data',(chunk)=>{str += chunk})res.on('end',()=>{console.log(JSON.parse(str))})
})
创建接口
const http = require("http")http.createServer((req,res) => {res.writeHead(200, {"content-type": "text/plain"})res.write("hello nodejs!")res.end()
}).listen(3000)console.log("http://localhost:3000")
打开浏览器:http://localhost:3000,展示如下
创建3000端口监听
const http = require("http")http.createServer((req,resp) => {let url = req.urlresp.writeHead(200, {'Content-Type': 'text/plain; charset=utf-8'});if(url == "/index"){let arr = ["apple","banana","orange"]resp.write(JSON.stringify(arr))} else if (url == "/main") {resp.write("你访问了主页")} else {resp.write("你访问的页面不存在,404")}resp.end()
}).listen(3000)
resp.writeHead(200, {‘Content-Type’: ‘text/plain; charset=utf-8’}); 设置响应头,设置字符集编码,防止返回乱码。
输出的内容:
1.2、文件读写
const fs = require('fs')
fs.writeFile('log.txt','hello', (err , data) => {if(err){console.log("file create sorry!")} else {console.log("file create successfully")}
})
1.3、进程的管理
function main(argv) {console.log(argv)}main(process.argv.slice(2))
控制台输出:
function main(argv) {console.log(argv)}main(process.argv)
控制台输出:
2、Node.Js 相关工具
2.1、版本查询方法
- npm view 包名pkg versions :查看服务器上包pkg的最新的版本信息
- npm ls 包名pkg -g :查看本地全局安装的pkg版本
- npm info 包名pkg :查看npm js服务器上包pkg的最新的版本信息,比npm view pkg version提供的信息更丰富
版本号:x.x.x
例如:5.2.3 主版本号 major:5 次版本号 minor:2 补丁号 patch:3
patch是奇数的话是不稳定的版本,如果是偶数的话则是稳定的版本
- npm outdated :查看过期的包信息
^ x.x.x :锁定主版本号,其他取最新;
~ x.x.x :锁定主版本和次版本号,其他取最新;
x.x.x :锁定主次补丁版本号;
2.2、npm 内置包
const path = require('path')console.log(__dirname);
// resolve 路径的解析
console.log(path.resolve(__dirname, '../'))
2.3、npm 第三方包
- -y: 所有的操作提示全部yes
- -g: 全局进行安装对应的包
使用npm下载第三方包,例如:axios,来请求调用网易接口
接口地址:https://api.vvhan.com/api/rand.music?type=json&sort=热歌榜
const axios = require('axios')axios.get("https://api.vvhan.com/api/rand.music?type=json&sort="+encodeURI("热歌榜"))
.then(res => {console.log(res)
})
.catch(err => {console.error(err);
})
nodejs使用axios进行http get请求时,报错TypeError [ERR_UNESCAPED_CHARACTERS]: Request path contains unescaped characters,其出现的原因是请求的url中携带中文参数。
解决方案:“https://api.vvhan.com/api/rand.music?type=json&sort=”+encodeURI(“热歌榜”)
下载lodash第三方包,测试如下:
const _ = require('lodash')let arr = [1,2,3,4,5,6]let double_arr = _.chunk(arr,2)console.log(double_arr)
输出的结果:
2.4、npm 自定义包
const _ = require("lodash")module.exports = function mychunk(arr){return _.chunk(arr,2)
}// 使用测试
const mychunk = require('./mychunk')let test_arr = [2,4,6,8]console.log(mychunk(test_arr))
测试结果:
2.5、npm 发布自定义包
查看npm源:npm config get registry
切换npm源方法一:npm config set registry http://registry.npmjs.org
切换npm源方法二:nrm use npm
PS C:\Users\16204\Desktop\Nodejs> npm adduser
npm notice Log in on https://registry.npmjs.org/
Username: wristwaking
Password:
Email: (this IS public) 1620444902@qq.com
上传的命令:npm publish
如果上传失败,检查包的名称,在package.json文件中修改name属性,原因是你的包名在npm已经存在。
2.6、npm 脚本
如果是并行执行(即同时的平行执行),可以使用 & 符号。
$ npm run script1 & npm run script2
如果是继发执行(即只有前一个任务成功,才执行下一个任务),可以使用 && 符号。
$ npm run script1 && npm run script2
常用的 npm 脚本简写形式:npm start 是 npm run start
npm 脚本有一个非常强大的功能,就是可以使用 npm 的内部变量。
首先,通过 npm_package_ 前缀,npm 脚本可以拿到 package.json 里面的字段。比如,下面是一个 package.json。
{"name": "foo", "version": "1.2.5","scripts": {"view": "node wrist.js"}
}
// wrist.js
console.log(process.env.npm_package_name); // foo
console.log(process.env.npm_package_version); // 1.2.5
npmpackage前缀也支持嵌套的package.json字段。
上面代码中,我们通过环境变量 process.env 对象,拿到 package.json 的字段值。如果是 Bash 脚本,可以用$npm_package_name 和 $npm_package_version 取到这两个值。
"repository": {"type": "git","url": "xxx"
},
scripts: {"view": "echo $npm_package_repository_type"
}
在window操作系统中:“echo %npm_package_repository_type%”
在Linux操作系统中:“echo $npm_package_repository_type”
2.7、npm 安装 Git 包
这样适合安装公司内部的git服务器上的项目
npm install git+https://git@github.com:lurongtao/gp-project.git
或者以ssh的方式
npm install git+ssh://git@github.com:lurongtao/gp-project.git
2.8、nrm 镜像源
NRM (npm registry manager)是npm的镜像源管理工具,有时候国外资源太慢,使用这个就可以快速地在 npm 源间切换。
查看当前源
npm config get registry
切换淘宝源
npm config set registry https://registry.npm.taobao.org
安装 nrm:在命令行执行命令,npm install -g nrm,全局安装nrm
使用 nrm:执行命令 nrm ls 查看可选的源。 其中,带*的是当前使用的源,上面的输出表明当前源是官方源。
切换 nrm:如果要切换到taobao源,执行命令nrm use taobao。
测试速度:你还可以通过 nrm test 测试相应源的响应时间。
2.9、npx 扩展小工具
NPX: npm package extention
npm 从5.2版开始,增加了 npx 命令。Node 自带 npm 模块,所以可以直接使用 npx 命令。万一不能用,就要手动安装一下。
主要作用1:调用项目安装的模块
npx 会自动查找当前依赖包中的可执行文件,如果找不到,就会去 PATH 里找。如果依然找不到,就会帮你安装!
npm install -g npx
npx 想要解决的主要问题,就是调用项目内部安装的模块。比如,项目内部安装了Mocha。
npm install -D mocha
一般来说,调用 Mocha ,只能在项目脚本和 package.json 的scripts字段里面,如果想在命令行下调用,必须像下面这样。
# 项目的根目录下执行
node-modules/.bin/mocha --version
npx 就是想解决这个问题,让项目内部安装的模块用起来更方便,只要像下面这样调用就行了。
npx mocha --version
npx 的原理很简单,就是运行的时候,会到node_modules/.bin路径和环境变量$PATH里面,检查命令是否存在。
主要作用2:避免全局安装模块
除了调用项目内部模块,npx 还能避免全局安装的模块。比如,create-react-app 这个模块是全局安装,npx 可以运行它,而且不进行全局安装。
npx create-react-app my-react-app
上面代码运行时,npx 将 create-react-app 下载到一个临时目录,使用以后再删除。所以,以后再次执行上面的命令,会重新下载 create-react-app。
注意,只要 npx 后面的模块无法在本地发现,就会下载同名模块。比如,本地没有安装http-server模块,下面的命令会自动下载该模块,在当前目录启动一个 Web 服务。
npx http-server
3、模块 / 包 与 Common.JS
前端模块化:
- AMD( require.js)
- CMD( sea.js )
- Common.Js( module.export / require )
- ES6 模块化( export / import )
3.1、模块化的区别
Common.Js:主要实践者为 Node.Js
1、commonjs模块输出的是值的拷贝,被模块缓存,在另一个模块可以修改赋值,当输出的是基本数据类型的时候,修改时不会影响到相应模块的值,当输出的是引用类型的值时,此时是浅拷贝,共享一个对象的地址,修改时会影响其他相关模块中的值。
2、当使用require命令加载某个模块时,就会运行整个模块的代码。当使用require命令加载同一个模块时,不会再执行该模块,而是取到缓存之中的值。也就是说,Commonjs模块无论加载多少次,都只会在第一次加载时运行一次,以后再加载,就返回第一次运行的结果,除非手动清除系统缓存。
3、循环加载时,属于加载时执行。即脚本代码在require的时候,就会全部执行。一旦出现某个模块被"循环加载",就只输出已经执行的部分,还未执行的部分不会输出。
ES6
1、输出的是动态只读引用, 在import一个模块时,会生成一个只读引用,不能进行修改。当执行需要用到该值时,才会根据只读引用去原模块中取值。如果在原模块中修改值,所有用到该值的模块中的引用值都会修改。
2、循环加载时,ES6模块是动态引用。只要两个模块之间存在某个引用,代码就能够执行。
3.2、模块 / 包 分类
Node.js 有三类模块,即内置的模块、第三方的模块、自定义的模块。
内置的模块
Node.js 内置模块又叫核心模块,Node.js安装完成可直接使用。如:
const path = require('path')
var extname = path.extname('index.html')
console.log(extname)
第三方的 Node.js 模块
第三方的Node.js模块指的是为了实现某些功能,发布的npmjs.org上的模块,按照一定的开源协议供社群使用。如:
npm install chalkconst chalk = require('chalk')
console.log(chalk.blue('Hello world!'))
自定义的Node.js模块
自定义的Node.js模块,也叫文件模块,是我们自己写的供自己使用的模块。同时,这类模块发布到npmjs.org上就成了开源的第三方模块。
自定义模块是在运行时动态加载,需要完整的路径分析、文件定位、编译执行过程、速度相比核心模块稍微慢一些,但是用的非常多。
const name = {username: '唤醒手腕',sayName() {console.log(this.username)}
}
const age = {age: 100
}
module.exports = {name,age
}## 测试const {name,age} = require("./app")
name.sayName()
console.log(age.age)
日常问题,案例:
const export = module.exports
export = { name , age }
## 运行失败:
原因:export原来的引用是module.exports,重新赋值{ name , age },引用被打破。
4、常用内置模块
这里介绍几个常用的内置模块:url, querystring, http, events, fs, stream, readline, crypto, zlib
4.1、内置模块 url
const url = require('url');const urlString = 'https://www.baidu.com:443/path/index.html?id=2#tag=3'console.log('show:', url.parse(urlString))## 结果:show: Url {protocol: 'https:',slashes: true,auth: null,host: 'www.baidu.com:443',port: '443',hostname: 'www.baidu.com',hash: '#tag=3',search: '?id=2',query: 'id=2',pathname: '/path/index.html',path: '/path/index.html?id=2',href: 'https://www.baidu.com:443/path/index.html?id=2#tag=3'
}
const url = require('url')url.resolve('http://example.com/', 'one')
// http://example.com/one
url.resolve('http://example.com/', '/one')
// http://example.com/one
url.resolve('http://example.com/one', '/two')
// http://example.com/two
4.2、内置模块 log4js
const log4js = require('log4js');var logger = log4js.getLogger();logger.level = 'debug';logger.debug('this is a debug log');
const log4js = require("log4js");log4js.configure({appenders: { cheese: { type: "file", filename: "cheese.log" } },categories: { default: { appenders: ["cheese"], level: "error" } }
});const logger = log4js.getLogger("cheese");logger.trace("Entering cheese testing");logger.debug("Got cheese.");logger.info("Cheese is Comté.");logger.warn("Cheese is quite smelly.");logger.error("Cheese is too ripe!");logger.fatal("Cheese was breeding ground for listeria.");
4.3、内置模块 http / https
const http = require('http')const server = http.createServer((req,resp) => {console.log('req = ', req)resp.end()
})server.listen(3000, () => {console.log('http://localhost:3000')
})
4.4、跨越解决方案 CORS
4.5、跨域解决方案 JSONP
const http = require('http')
const url = require('url')const app = http.createServer((req, res) => {let urlObj = url.parse(req.url, true)switch (urlObj.pathname) {case '/api/user':res.end(`${urlObj.query.cb}({"name": "唤醒手腕"})`)breakdefault:res.end('404.')break}
})app.listen(8080, () => {console.log('localhost:8080')
})
4.6、内置模块 fs
文件夹的操作,文件的基本读写操作
const fs = require("fs")fs.mkdir('log',(err)=>{console.log('create successfully', '')
})fs.rename('log','newdir',()=>{console.log('rename successfully', '')
})fs.rmdir('newdir',()=>{console.log('remove dir successfully', '')
})fs.readdir('log',(err, files)=>{console.log(files)
})// 写文件
fs.writeFile('./log/test.txt','hello wristwaking',()=>{console.log('write txt successfully', '')
})// 追加写入
fs.appendFile('./log/test.txt','new world',()=>{console.log('append txt successfully', '')
})// 读文件fs.readFile('./log/helloword.txt',(err,data)=>{console.log('data:', data.toString())
})
fs.readFile('./log/helloword.txt','utf-8',(err,data)=>{console.log('data:', data)
})// remove file
fs.unlink('./log/test.txt',()=>{console.log('delete file successfully', '')
})
关于文件读写的同步方法代码
const fsPromise = require('fs/promises')data = fsPromise.readFile('./log/helloword.txt') newdata = data.then((result)=>{console.log('tag', result.toString())
})console.log('newdata = ', newdata)
批量的写入文件的方式
// 批量写文件for (var i = 0; i < 10; i++) {fs.writeFile(`./logs/log-${i}.txt`, `log-${i}`, (err) => {console.log('done.')})
}
读取文件的目录
// 读取文件/目录信息fs.readdir('./', (err, data) => {data.forEach((value, index) => {fs.stat(`./${value}`, (err, stats) => {// console.log(value + ':' + stats.size)console.log(value + ' is ' + (stats.isDirectory() ? 'directory' : 'file'))})})
})
文件流的读写操作 / 文件压缩
const fs = require('fs')const zlib = require('zlib')const gzip = zlib.createGzip()const readStream = fs.createReadStream('./log/helloword.txt')const writeStream = fs.createWriteStream('./log/helloword2.txt')readStream.pipe(gzip).pipe(writeStream)
4.7、实现爬虫功能 cheerio
选取网页url,使用http协议get到网页数据
豆瓣TOP250链接地址:https://movie.douban.com/top250
首先我们请求http协议,通过http来拿到网页的所有数据
const https = require('https');
https.get('https://movie.douban.com/top250',function(res){// 分段返回的 自己拼接let html = '';// 有数据产生的时候 拼接res.on('data',function(chunk){html += chunk;})// 拼接完成res.on('end',function(){console.log(html);})
})
上面代码呢,大家一定要注意我们请求数据时,拿到的数据是分段拿到的,我们需要通过自己把数据拼接起来
res.on('data',function(chunk){html += chunk;})
拼接完成时 我们可以输出一下,看一下我们是否拿到了完整数据
res.on('end',function(){console.log(html);})
二、使用cheerio工具解析需要的内容
const cheerio = require('cheerio');res.on('end',function(){console.log(html);const $ = cheerio.load(html);let allFilms = [];$('li .item').each(function(){// this 循环时 指向当前这个电影// 当前这个电影下面的title// 相当于this.querySelector const title = $('.title', this).text();const star = $('.rating_num',this).text();const pic = $('.pic img',this).attr('src');// console.log(title,star,pic);// 存 数据库// 没有数据库存成一个json文件 fsallFilms.push({title,star,pic})}
}
下面就是保存数据了,我将数据保存在 films.json 文件中 将数据保存到文件中,我们引入一个fs模块,将数据写入文件中去
const fs = require('fs');
fs.writeFile('./films.json', JSON.stringify(allFilms),function(err){if(!err){console.log('文件写入完毕');}
})
源码展示:
// 请求 url - > html(信息) -> 解析html
const https = require('https');
const cheerio = require('cheerio');
const fs = require('fs');
// 请求 top250
// 浏览器输入一个 url, get
https.get('https://movie.douban.com/top250',function(res){// console.log(res);// 分段返回的 自己拼接let html = '';// 有数据产生的时候 拼接res.on('data',function(chunk){html += chunk;})// 拼接完成res.on('end',function(){console.log(html);const $ = cheerio.load(html);let allFilms = [];$('li .item').each(function(){// this 循环时 指向当前这个电影// 当前这个电影下面的title// 相当于this.querySelector const title = $('.title', this).text();const star = $('.rating_num',this).text();const pic = $('.pic img',this).attr('src');// console.log(title,star,pic);// 存 数据库// 没有数据库存成一个json文件 fsallFilms.push({title,star,pic})})// 把数组写入json里面fs.writeFile('./films.json', JSON.stringify(allFilms),function(err){if(!err){console.log('文件写入完毕');}})// 图片下载一下downloadImage(allFilms);})
})function downloadImage(allFilms) {for(let i=0; i<allFilms.length; i++){const picUrl = allFilms[i].pic;// 请求 -> 拿到内容// fs.writeFile('./xx.png','内容')https.get(picUrl,function(res){res.setEncoding('binary');let str = '';res.on('data',function(chunk){str += chunk;})res.on('end',function(){fs.writeFile(`./images/${i}.png`,str,'binary',function(err){if(!err){console.log(`第${i}张图片下载成功`);}})})})}
}
传统的request方式,封装请求到html数据。
5、Node.Js 连接数据库
5.1、连接 MySQL 数据库
两种方式:1. 基本连接数据库;2. 采用Pool连接池技术连接数据库
基本连接数据库
const mysql = require('mysql')console.log('mysql: ', mysql)const DataBaseConfig={host:"localhost",user:"root",password:"root",port:"3306",database:"nodedb"
}
let connect = mysql.createConnection(DataBaseConfig)//开始链接数据库
connect.connect(function(err){if(err) {console.log(`mysql连接失败: ${err}`);} else {console.log("mysql连接成功");}
});const Sql_Query = 'select * from people'connect.query(Sql_Query, function(err, result) {console.log(result);closeMysql(connect)
});//查询成功后关闭 mysql
function closeMysql(connect){connect.end((err)=>{if(err){console.log(`mysql关闭失败:${err}`);}else{console.log('mysql关闭成功');}});
}
采用Pool连接池技术连接数据库
通过连接池 createPool() 方法连接数据库的方式与通过 createConnection() 方法用法一致;然后通过 getConnection() 方法来对数据库进行连接, release() 释放连接池中的数据库连接。
注意只是单纯的释放并没有关闭,如果有下次对数据库的访问还是会用上的;pool.end() 方法是关闭连接池,完全关闭可以理解为对数据库的完全关闭;
let mysql = require("mysql");
const db_config={host:"localhost",user:"root",password:"root",port:"3306",database:"nodedb"
}
let pool = mysql.createPool(db_config);
pool.getConnection(function(err , connect){// 通过getConnection()方法 进行数据库连接if (err) {console.log(`mysql链接失败 : ${err}`);} else {connect.query('select * from people', function(err , result){if (err) {console.log(`SQL error : ${err}`)} else {console.log(result);connect.release();// 释放连接池中的数据库连接pool.end();// 关闭连接池}});}
});
唤醒手腕 - 前端服务器端开发 Node.Js 学习笔记(学习中,更新中)相关推荐
- JavaScript之后端Web服务器开发Node.JS基本模块学习篇
JavaScript之后端Web服务器开发Node.JS基本模块学习篇 基本模块 fs文件系统模块 stream支持流模块 http crypto加密模块 基本模块 因为Node.js是运行在服务区端 ...
- Go语言开发学习笔记(持续更新中)
Go语言开发学习笔记(持续更新中) 仅供自我学习 更好的文档请选择下方 https://studygolang.com/pkgdoc https://www.topgoer.com/go%E5%9F% ...
- C语言学习笔记Day3——持续更新中... ...
上一篇文章C语言学习笔记Day2--持续更新中- - 八. 容器 1. 一维数组 1.1 什么是一维数组 当数组中每个元素都只带有一个下标(第一个元素的下标为0, 第二个元素的下标为1, 以此类推)时 ...
- 【前端】-【node.js基础】-学习笔记
[前端]-[node.js]-学习笔记 1 node.js介绍 1.1 node.js优点 1.2 node.js 不足之处 1.3 nodejs与java的区别 2. node中函数 3. 浏览器和 ...
- Node.js零基础自学(持续更新中)
1. Node.js时基于Chrome V8 引擎的JavaScript运行环境.官网:Node.jsNode.js® is a JavaScript runtime built on Chrome' ...
- vins中imu融合_小觅智能 | VINS 学习笔记(持续更新中)
VINS 基本介绍 VINS-Mono 和 VINS-Mobile 是香港科技大学沈劭劼老师开源的单目视觉惯导 SLAM 方案.2017年发表于<IEEE Transactions on Rob ...
- Spring、SpringMVC、SpringBoot及其插件学习笔记集合(持续更新中....)
笔记目录 语言 1.MyBatis 1.1 普通用法 1.1.1 配置文件 1.1.2 mapper文件 1.2 通用mapper文件 2.Thymeleaf 2.1 命名空间 2.2 依赖 2.3 ...
- Git和GitHub学习笔记 V2.0(更新中...)
文章目录 1. 什么是Git? 2. 为什么要使用Git? 3. Git和Svn的区别 4. Git的历史 5. 版本控制工具应该具备哪些功能 6. 安装Git 7. Git的三区和三种状态 8. G ...
- Vue3+TypeScript+Vite 学习笔记(持续更新中)
文章目录 一.Vue3 基础环境配置 1. 检查当前 node 版本:(`需要 node 在10 及以上`) 2. 安装 vue-cli 脚手架: 3.创建项目: 4. 自定义Eslint 规则: 二 ...
最新文章
- centos7下没有iptables进行安装或更新
- 网站外链的存在有什么作用呢?
- python小案例下载_python 小案例demo06
- python定时器 循环_python从写定时器学习Thread
- (转)深度学习是经验主义新高峰,不是理性主义终结
- 数模电路基础知识 —— 3. 常见电路符号说明(电容、电阻、电感)
- 利用VGA输出音频信号
- Zeppelin0.8.1上操作hive(使用jdbc解释器)
- 语音预处理之分帧加窗
- JAVA游戏土行孙_《封神榜》土行孙,被誉为国内最知名矮星,现惨淡靠低保度日...
- 就业和工作?毕业生何去何从?
- Tableau画桑基图
- 网易im聊天室的集成
- Vue 项目前端响应式布局及框架搭建
- 朵拉影像开发 又一个昫暖的午后
- 接口VGA、DVI、HDMI、DP详解
- 最新骗术,骗子的手段越来越高了(转贴)
- 关于一些常见/好用的matlab工具箱介绍
- kendoui grid lov增强
- html整理,常用标签
热门文章
- blazeds TypeError: Error #1034: 强制转换类型失败
- vue实现时间戳格式化
- 大学学了一年Python之后开始兼职,平均每个月赚3030块
- CSS 样式表{二}
- vue create is a Vue CLI 3 only command and you are using Vue CLI 2.9.6.
- 揭开CFA的前世今生,解读考证究竟是为了什么?
- 记录一下spring静态获取bean的工具类
- matlab仿真雷达方程,雷达方程分析(示例代码)
- 企业信息安全之商业间谍
- mybatis中case when用法以及@Param用法