唤醒手腕 - 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、版本查询方法

  1. npm view 包名pkg versions :查看服务器上包pkg的最新的版本信息
  2. npm ls 包名pkg -g :查看本地全局安装的pkg版本
  3. npm info 包名pkg :查看npm js服务器上包pkg的最新的版本信息,比npm view pkg version提供的信息更丰富

版本号:x.x.x
例如:5.2.3 主版本号 major:5 次版本号 minor:2 补丁号 patch:3
patch是奇数的话是不稳定的版本,如果是偶数的话则是稳定的版本

  1. 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

前端模块化:

  1. AMD( require.js)
  2. CMD( sea.js )
  3. Common.Js( module.export / require )
  4. 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 学习笔记(学习中,更新中)相关推荐

  1. JavaScript之后端Web服务器开发Node.JS基本模块学习篇

    JavaScript之后端Web服务器开发Node.JS基本模块学习篇 基本模块 fs文件系统模块 stream支持流模块 http crypto加密模块 基本模块 因为Node.js是运行在服务区端 ...

  2. Go语言开发学习笔记(持续更新中)

    Go语言开发学习笔记(持续更新中) 仅供自我学习 更好的文档请选择下方 https://studygolang.com/pkgdoc https://www.topgoer.com/go%E5%9F% ...

  3. C语言学习笔记Day3——持续更新中... ...

    上一篇文章C语言学习笔记Day2--持续更新中- - 八. 容器 1. 一维数组 1.1 什么是一维数组 当数组中每个元素都只带有一个下标(第一个元素的下标为0, 第二个元素的下标为1, 以此类推)时 ...

  4. 【前端】-【node.js基础】-学习笔记

    [前端]-[node.js]-学习笔记 1 node.js介绍 1.1 node.js优点 1.2 node.js 不足之处 1.3 nodejs与java的区别 2. node中函数 3. 浏览器和 ...

  5. Node.js零基础自学(持续更新中)

    1. Node.js时基于Chrome V8 引擎的JavaScript运行环境.官网:Node.jsNode.js® is a JavaScript runtime built on Chrome' ...

  6. vins中imu融合_小觅智能 | VINS 学习笔记(持续更新中)

    VINS 基本介绍 VINS-Mono 和 VINS-Mobile 是香港科技大学沈劭劼老师开源的单目视觉惯导 SLAM 方案.2017年发表于<IEEE Transactions on Rob ...

  7. 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 ...

  8. Git和GitHub学习笔记 V2.0(更新中...)

    文章目录 1. 什么是Git? 2. 为什么要使用Git? 3. Git和Svn的区别 4. Git的历史 5. 版本控制工具应该具备哪些功能 6. 安装Git 7. Git的三区和三种状态 8. G ...

  9. Vue3+TypeScript+Vite 学习笔记(持续更新中)

    文章目录 一.Vue3 基础环境配置 1. 检查当前 node 版本:(`需要 node 在10 及以上`) 2. 安装 vue-cli 脚手架: 3.创建项目: 4. 自定义Eslint 规则: 二 ...

最新文章

  1. centos7下没有iptables进行安装或更新
  2. 网站外链的存在有什么作用呢?
  3. python小案例下载_python 小案例demo06
  4. python定时器 循环_python从写定时器学习Thread
  5. (转)深度学习是经验主义新高峰,不是理性主义终结
  6. 数模电路基础知识 —— 3. 常见电路符号说明(电容、电阻、电感)
  7. 利用VGA输出音频信号
  8. Zeppelin0.8.1上操作hive(使用jdbc解释器)
  9. 语音预处理之分帧加窗
  10. JAVA游戏土行孙_《封神榜》土行孙,被誉为国内最知名矮星,现惨淡靠低保度日...
  11. 就业和工作?毕业生何去何从?
  12. Tableau画桑基图
  13. 网易im聊天室的集成
  14. Vue 项目前端响应式布局及框架搭建
  15. 朵拉影像开发 又一个昫暖的午后
  16. 接口VGA、DVI、HDMI、DP详解
  17. 最新骗术,骗子的手段越来越高了(转贴)
  18. 关于一些常见/好用的matlab工具箱介绍
  19. kendoui grid lov增强
  20. html整理,常用标签

热门文章

  1. blazeds TypeError: Error #1034: 强制转换类型失败
  2. vue实现时间戳格式化
  3. 大学学了一年Python之后开始兼职,平均每个月赚3030块
  4. CSS 样式表{二}
  5. vue create is a Vue CLI 3 only command and you are using Vue CLI 2.9.6.
  6. 揭开CFA的前世今生,解读考证究竟是为了什么?
  7. 记录一下spring静态获取bean的工具类
  8. matlab仿真雷达方程,雷达方程分析(示例代码)
  9. 企业信息安全之商业间谍
  10. mybatis中case when用法以及@Param用法