文章目录
模块/包 与 CommonJS
1、模块/包分类
Node.js 有三类模块,即内置的核心模块、第三方的模块、自定义的模块。
1.1 内置的模块
Node.js 内置模块又叫核心模块,Node.js安装完成可直接使用。如:
const path = require('path');
console.log(path.extname('index.html'));
1.2 第三方的Node.js模块
第三方的Node.js模块指的是为了实现某些功能,发布的npmjs.org上的模块,按照一定的开源协议供社群使用。如:
npm install chalk
const chalk = require('chalk')
console.log(chalk.blue('Hello world!'))
1.3 自定义的Node.js模块
自定义的Node.js模块,也叫文件模块,是我们自己写的供自己使用的模块。同时,这类模块发布到npmjs.org上就成了开源的第三方模块。
自定义模块是在运行时动态加载,需要完整的路径分析、文件定位、编译执行过程、速度相比核心模块稍微慢一些,但是用的非常多。
2、CommonJS
CommonJs 是一种 JavaScript 语言的模块化规范,它通常会在服务端的 Nodejs上使用。项目是由多个模块组成的,模块和模块之间的调用,需要各个模块有相同规范的 API,这样一来在使用的过程中不会有那么多的学习成本,并且对于单个模块来说是类聚的。
2.1 模块定义、接口暴露和引用接口
在 CommonJs的模块化规范中,每一个文件就是一个模块,拥有自己独立的作用域、变量、以及方法等,对其他的模块都不可见。CommonJS规范规定,每个模块内部,module变量代表当前模块。这个变量是一个对象,它的 exports 属性(module.exports)是对外的接口。加载某个模块,其实是加载该模块的 module.exports 属性。require方法用于加载模块。
创建m1.js文件,添加内容,定义模块m1
const name = '19'
const sayName = () => {
console.log(name)
}
console.log('module 1')
// 接口暴露方法一:
module.exports = {
say: sayName
}
// 接口暴露方法二:
exports.say = sayName
// 错误!
exports = {
say: sayName
}
在main.js中引用模块m1
const m1 = require('./m1')
m1.say()
常用内置模块
1. url
1.1 parse
url.parse(urlString[, parseQueryString[, slashesDenoteHost]]);将url解析为一个对象
const url = require('url');
const urlStr = 'http://www.baidu.com:443/path/index.html?id=2#tag=3';
console.log(url.parse(urlStr));
运行结果
1.2 format
url.format(urlObject);将一个url对象解析成一个字符串。
const url = require('url')
const urlObj {
protocol: 'http:',
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: 'http://www.baidu.com:443/path/index.html?id=2#tag=3'
};
const urlTest = url.format(urlObject)
console.log(urlTest )
运行结果
1.3 resolve
url.resolve(from, to) 按规则解析url
const url = require('url');
console.log(url.resolve('https://www.baidu.com/a', '../'));
console.log(url.resolve('https://www.baidu.com/a', '/b'));
运行结果
1.4 URLSearchParams
解析url中?
后边的内容
const url = require('url');
const urlStr = 'http://www.baidu.com:443/path/index.html?id=2#tag=3';
const urlParams = new URLSearchParams(url.parse(urlStr).search);
console.log(urlParams.get('id'));//获取id
运行结果
2、querystring
2.1 parse
querystring.parse(str[, sep[, eq[, options]]]);将字符串解析为对象
const querystring = require('querystring')
var s = 'x=3/&y=4'
//参数一:每组key,value之间的分隔符,参数二:key,value之间的分隔符
var parsed = querystring.parse(s, '&', '=')
var parsed = querystring.parse(s)
console.log(parsed)
运行结果
带参数
不带参数
2.2 stringify
querystring.stringify(obj[, sep[, eq[, options]]])
const querystring = require('querystring')
var o = {
x: 3,
y: '位'
}
//带参数,参数一:每组key,value之间的分隔符,参数二:key,value之间的分隔符
var parsed1 = querystring.stringify(o, ':', '/')
//不带参数
var parsed2 = querystring.stringify(o)
//不将中文编码
var parsed3 = querystring.stringify(o, null, null, {
encodeURIComponent(string) {
return querystring.unescape(string);
}
})
console.log(parsed3)
带参数运行结果(会默认将中文编码)
不带参数运行结果
不将中文编码
2.3 escape/unescape
querystring.escape(str)将字符串编码
const querystring = require('querystring')
var str = 'id=3&city=北京&url=https://www.baidu.com'
var escaped = querystring.escape(str)
console.log(escaped)
querystring.unescape(str)
const querystring = require('querystring')
var str = 'id%3D3%26city%3D%E5%8C%97%E4%BA%AC%26url%3Dhttps%3A%2F%2Fwww.baidu.com'
var unescaped = querystring.unescape(str)
console.log(unescaped)
3、http/https
3.1 get
var http = require('http')
var https = require('https')
// 1、接口 2、跨域
const server = http.createServer((request, response) => {
var url = request.url.substr(1)
var data = ''
response.writeHeader(200, {
//默认,会自动解析html代码
'content-type': 'text/html',
//不会自动解析html代码
//'content-type': 'text/plain',
//返回json字符串
//'content-type': 'application/json;charset=utf-8',
//'Access-Control-Allow-Origin': '*'
})
//会在前端页面显示 hello,并且需要在后边加上end停止
//response.write('hello')
//response.end();
https.get(`https://m.lagou.com/listmore.json${url}`, (res) => {
res.on('data', (chunk) => {
data += chunk
})
res.on('end', () => {
response.end(JSON.stringify({
ret: true,
data
}))
})
})
})
server.listen(8080, () => {
console.log('localhost:8080')
})
3.2 post:服务器提交
const https = require('https')
const querystring = require('querystring')
const postData = querystring.stringify({
province: '上海',
city: '上海',
district: '宝山区',
address: '同济支路199号智慧七立方3号楼2-4层',
latitude: 43.0,
longitude: 160.0,
message: '求购一条小鱼',
contact: '13666666',
type: 'sell',
time: 1571217561
})
const options = {
protocol: 'https:',
hostname: 'ik9hkddr.qcloud.la',
method: 'POST',
port: 443,
path: '/index.php/trade/add_item',
headers: {
'Content-Type': 'application/x-www-form-urlencoded',
'Content-Length': Buffer.byteLength(postData)
}
}
function doPost() {
let data
let req = https.request(options, (res) => {
res.on('data', chunk => data += chunk)
res.on('end', () => {
console.log(data)
})
})
req.write(postData)
req.end()
}
// setInterval(() => {
// doPost()
// }, 1000)
3.3 跨域:jsonp
利用的是在浏览器端请求一个js不跨域的特性
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": "gp145"})`)
break
default:
res.end('404.')
break
}
})
app.listen(8080, () => {
console.log('localhost:8080')
})
3.4 跨域:CORS
跨源资源共享
const http = require('http')
const url = require('url')
const querystring = require('querystring')
const app = http.createServer((req, res) => {
let data = ''
let urlObj = url.parse(req.url, true)
res.writeHead(200, {
'content-type': 'application/json;charset=utf-8',
//跨域
'Access-Control-Allow-Origin': '*'
})
req.on('data', (chunk) => {
data += chunk
})
req.on('end', () => {
responseResult(querystring.parse(data))
})
function responseResult(data) {
switch (urlObj.pathname) {
case '/api/login':
res.end(JSON.stringify({
message: data
}))
break
default:
res.end('404.')
break
}
}
})
app.listen(8080, () => {
console.log('localhost:8080')
})
3.5 跨域:middleware(http-proxy-middware)
const http = require('http')
const proxy = require('http-proxy-middleware')
http.createServer((req, res) => {
let url = req.url
res.writeHead(200, {
'Access-Control-Allow-Origin': '*'
})
if (/^\/api/.test(url)) {
let apiProxy = proxy('/api', {
target: 'https://m.lagou.com',
changeOrigin: true,
pathRewrite: {
'^/api': ''
}
})
// http-proy-middleware 在Node.js中使用的方法
apiProxy(req, res)
} else {
switch (url) {
case '/index.html':
res.end('index.html')
break
case '/search.html':
res.end('search.html')
break
default:
res.end('[404]page not found.')
}
}
}).listen(8080)
4、Events
const EventEmitter = require('events')
//继承
class MyEventEmitter extends EventEmitter {}
//实例
const event = new MyEventEmitter()
//定义play事件
event.on('play', (movie) => {
console.log(movie)
})
//该事件只能触发一次
event.once('play1', (movie) => {
console.log(movie)
})
//触发play事件
event.emit('play', '我')
event.emit('play', '中国')
5、File System
const fs = require('fs')
const fsP = require('fs').promises
// 创建文件夹
//参数一:文件名
//参数二:错误优先的回调函数
fs.mkdir('./logs', (err) => {
console.log('done.')
})
// 文件夹改名
fs.rename('./logs', './log', () => {
console.log('done')
})
// 读取文件夹
fs.readdir('./logs', (err, result) => {
//返回文件夹下的文件名数组
console.log(result)
})
// 删除文件夹
fs.rmdir('./log', () => {
console.log('done.')
})
// 写内容到文件里
fs.writeFile(
//要写入的文件
'./logs/log1.txt',
//要写入的内容
'hello',
// 错误优先的回调函数
(err) => {
if (err) {
console.log(err.message)
} else {
console.log('文件创建成功')
}
}
)
// 给文件追加内容
fs.appendFile('./logs/log1.txt', '\nworld', () => {
console.log('done.')
})
// 读取文件内容
//参数二:读出结果采用utf-8编码
fs.readFile('./logs/log1.txt', 'utf-8', (err, data) => {
console.log(data)
})
// 删除文件
fs.unlink('./logs/log1.txt', (err) => {
console.log('done.')
})
// 批量写文件
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'))
})
})
})
// 同步读取文件
try {
const content = fs.readFileSync('./logs/log-1.txt', 'utf-8')
console.log(content)
console.log(0)
} catch (e) {
console.log(e.message)
}
console.log(1)
// 异步读取文件:方法一
fs.readFile('./logs/log-0.txt', 'utf-8', (err, content) => {
console.log(content)
console.log(0)
})
console.log(1)
// 异步读取文件:方法二
fs.readFile('./logs/log-0.txt', 'utf-8').then(result => {
console.log(result)
})
// 异步读取文件:方法三
function getFile() {
return new Promise((resolve) => {
fs.readFile('./logs/log-0.txt', 'utf-8', (err, data) => {
resolve(data)
})
})
}
;(async () => {
console.log(await getFile())
})()
// 异步读取文件:方法四
const fsp = fsP.readFile('./logs/log-1.txt', 'utf-8').then((result) => {
console.log(result)
})
console.log(fsP)
// watch 监测文件变化
fs.watch('./logs/log-0.txt', () => {
console.log(0)
})
fs.watchFile('./logs/log-0.txt', () => {
console.log(1)
})
6、Stream
const fs = require('fs')
//读流
const readstream = fs.createReadStream('./note.txt')
//写流
const writestream = fs.createWriteStream('./note2.txt')
writestream.write(readstream)
7、Zlib
const fs = require('fs')
//压缩
const zlib = require('zlib')
const gzip = zlib.createGzip()
const readstream = fs.createReadStream('./note.txt')
const writestream = fs.createWriteStream('./note2.gzip')
readstream
//压缩
.pipe(gzip)
.pipe(writestream)
//writestream.write(readstream)
8、ReadLine
//一行一行的读
const readline = require('readline')
const rl = readline.createInterface({
//标准输入
input: process.stdin,
//标准输出
output: process.stdout
})
//会停下来等你输入,输入完成后再继续往下走
rl.question('What do you think of Node.js? ', (answer) => {
// 输入的答案保存在answer中
console.log(`Thank you for your valuable feedback: ${answer}`)
rl.close()
})
9、Crypto
加密:既可作对称加密,也可做非对称加密,还可以做MD5加密、sha加密
const crypto = require('crypto')
const secret = 'abcdefg'
//参数一:加密算法
//参数二:加密对象
const hash = crypto.createHmac('sha256', secret)
//若有中文,要加编码方式
.update('I love you', /*'utf-8'*/)
//以16进制去加密
.digest('hex')
console.log(hash)
路由
var http = require('http')
var fs = require('fs')
http.createServer( function ( req, res ) {
switch ( req.url ) {
case '/home':
res.write('home')
res.end()
break
case '/mine':
res.write('mine')
res.end()
break
case '/login':
fs.readFile( './static/login.html',function ( error , data ) {
if ( error ) throw error
res.write( data )
res.end()
})
break
case '/fulian.jpg':
fs.readFile( './static/fulian.jpg', 'binary', function( error , data ) {
if( error ) throw error
res.write( data, 'binary' )
res.end()
})
break
default:
break
}
}).listen( 8000, 'localhost', function () {
console.log( '服务器运行在: http://localhost:8000' )
})