Stream 流
- 什么是流? Node中为什么要有流这个概念 ? 使用场景?
- 流指的是数据流,指的是数据是分片传输
- 数据可以实现非阻塞
- gulp 【 流式操作 】
案例: 打包压缩包
流程:
-
- 读取文件
-
- 创建压缩包
-
- 将读取的数据流写入压缩包
-
- 输出压缩包
vconst fs = require('fs') // 读取xxx.txt文件
const zlib = require('zlib') // 创建压缩包
// const inp = fs.createReadStream( 路径 )
const inp = fs.createReadStream( './xxx.txt' ) //读取数据路径
const gzip = zlib.createGzip() // 创建压缩包
// const outp = fs.createWriteStream(路径)
const outp = fs.createWriteStream( './xxx.txt.gz' )
inp
.pipe( gzip )
.pipe( outp )
自定义模块
// 1. 创建模块
const name = {
id: 1,
name: 'zhangsan'
}
const str = 'sdaf'
// 2. 导出模块
// module.exports = name 只能导出一个
module.exports = { // 批量导出
name,
str
}
//3. 模块的导入
// const { name,str } = require(路径)
const { name,str } = require('./02-name.js')
console.log( name.name , str )
第三方模块:
我们一般都是从npmjs.com这个网站拉取
使用流程:
1. 安装
npm init -y
先创建package.json 文件
npm/cnpm i request -S/-D
-S --save 生产环境
-D --save-dev dev development的简写 开发环境
2. 使用
request这个模块是做数据请求
3. Node中数据请求存在跨域吗?
不存在
const request = require('request')
request('https://m.lagou.com/listmore.json',( a,b,c ) => {
console.log( 'a',a ) // error
console.log( 'b',b ) // response 返回所有结果
console.log( 'c',c ) // body 数据 string
})
HTTP
-
Node.js读取文件都是二进制流
-
Buffer
-
binary
const fs = require( 'fs' ) fs.readFile('./yyb.txt',( error, docs ) => { console.log( docs.toString() ) }) 会出现乱码 fs.readFile('./yyb.txt','utf8',( error, docs ) => { console.log( docs.toString() ) }) 加上UTF-8编码则不会出现乱码
http模块
- http.get
- http.request
- 业务: 从nowapi中找一个免费接口,进行数据请求
HTTP.GET
const http = require('http');
//http://api.k780.com/?app=weather.lifeindex&weaid=1&appkey=10003&sign=b59bc3ef6191eb9f747dd4e83c99f2a4&format=json
http.get('http://api.k780.com/?app=weather.lifeindex&weaid=1&appkey=*****&sign=********************************&format=json', (res) => {
const { statusCode } = res; //获取请求状态码 200 304 404 500 301 302
const contentType = res.headers['content-type']; //获取请求数据类型
//josn数据的content-type 'content-type':'application/json'
let error;
if (statusCode != 200) {
//如果状态码不是200,输出报错信息
error = new Error('Request Failed.\n' +
`Status Code: ${statusCode}`);
} else if (!/^application\/json/.test(contentType)) {
error = new Error('Invalid content-type.\n' +
`Expected application/json but received ${contentType}`);
}
if (error) { //如果报错了,将报错信息存入日志
console.error(error.message);
// consume response data to free up memory
res.resume();
return;
}
res.setEncoding('utf8');
let rawData = '';
res.on('data', (chunk) => { rawData += chunk; }); //通过data事件拼接数据流
res.on('end', () => { //获取数据流
try { //高级编程语法 捕获错误信息
const parsedData = JSON.parse(rawData);
console.log(parsedData);
} catch (e) {
console.error(e.message);
}
});
}).on('error', (e) => {
console.error(`Got error: ${e.message}`);
});
{ success: '1',
result:
[ { weaid: '1',
days: '',
week_1: '',
simcode: 'beijing',
citynm: '北京',
cityid: '101010100',
lifeindex_uv_id: '110',
lifeindex_uv_typeno: 'uv',
lifeindex_uv_typenm: '紫外线指数',
lifeindex_uv_attr: '最弱',
lifeindex_uv_dese: '辐射弱,涂擦SPF8-12防晒护肤品。',
lifeindex_xt_id: '147',
lifeindex_xt_typeno: 'xt',
lifeindex_xt_typenm: '血糖指数',
lifeindex_xt_attr: '易波动',
lifeindex_xt_dese: '气温多变,血糖易波动,请注意监测。',
lifeindex_ct_id: '121',
lifeindex_ct_typeno: 'ct',
lifeindex_ct_typenm: '穿衣指数',
lifeindex_ct_attr: '炎热',
lifeindex_ct_dese: '建议穿短衫、短裤等清凉夏季服装。',
lifeindex_xc_id: '118',
lifeindex_xc_typeno: 'xc',
lifeindex_xc_typenm: '洗车指数',
lifeindex_xc_attr: '不宜',
lifeindex_xc_dese: '有雨,雨水和泥水会弄脏爱车。',
lifeindex_kq_id: '109',
lifeindex_kq_typeno: 'kq',
lifeindex_kq_typenm: '空气污染扩散指数',
lifeindex_kq_attr: '良',
lifeindex_kq_dese: '气象条件有利于空气污染物扩散。' },
{ weaid: '1',
days: '',
week_1: '',
simcode: 'beijing',
citynm: '北京',
cityid: '101010100',
lifeindex_uv_id: '110',
lifeindex_uv_typeno: 'uv',
lifeindex_uv_typenm: '紫外线指数',
lifeindex_uv_attr: '最弱',
lifeindex_uv_dese: '辐射弱,涂擦SPF8-12防晒护肤品。',
lifeindex_xt_id: '147',
lifeindex_xt_typeno: 'xt',
lifeindex_xt_typenm: '血糖指数',
lifeindex_xt_attr: '易波动',
lifeindex_xt_dese: '气温多变,血糖易波动,请注意监测。',
lifeindex_ct_id: '122',
lifeindex_ct_typeno: 'ct',
lifeindex_ct_typenm: '穿衣指数',
lifeindex_ct_attr: '热',
lifeindex_ct_dese: '适合穿T恤、短薄外套等夏季服装。',
lifeindex_xc_id: '118',
lifeindex_xc_typeno: 'xc',
lifeindex_xc_typenm: '洗车指数',
lifeindex_xc_attr: '不宜',
lifeindex_xc_dese: '有雨,雨水和泥水会弄脏爱车。',
lifeindex_kq_id: '109',
lifeindex_kq_typeno: 'kq',
lifeindex_kq_typenm: '空气污染扩散指数',
lifeindex_kq_attr: '良',
lifeindex_kq_dese: '气象条件有利于空气污染物扩散。' },
{ weaid: '1',
days: '',
week_1: '',
simcode: 'beijing',
citynm: '北京',
cityid: '101010100',
lifeindex_uv_id: '107',
lifeindex_uv_typeno: 'uv',
lifeindex_uv_typenm: '紫外线指数',
lifeindex_uv_attr: '中等',
lifeindex_uv_dese: '涂擦SPF大于15、PA+防晒护肤品。',
lifeindex_xt_id: '147',
lifeindex_xt_typeno: 'xt',
lifeindex_xt_typenm: '血糖指数',
lifeindex_xt_attr: '易波动',
lifeindex_xt_dese: '气温多变,血糖易波动,请注意监测。',
lifeindex_ct_id: '121',
lifeindex_ct_typeno: 'ct',
lifeindex_ct_typenm: '穿衣指数',
lifeindex_ct_attr: '炎热',
lifeindex_ct_dese: '建议穿短衫、短裤等清凉夏季服装。',
lifeindex_xc_id: '118',
lifeindex_xc_typeno: 'xc',
lifeindex_xc_typenm: '洗车指数',
lifeindex_xc_attr: '不宜',
lifeindex_xc_dese: '有雨,雨水和泥水会弄脏爱车。',
lifeindex_kq_id: '106',
lifeindex_kq_typeno: 'kq',
lifeindex_kq_typenm: '空气污染扩散指数',
lifeindex_kq_attr: '中',
lifeindex_kq_dese: '易感人群应适当减少室外活动。' },
{ weaid: '1',
days: '',
week_1: '',
simcode: 'beijing',
citynm: '北京',
cityid: '101010100',
lifeindex_uv_id: '107',
lifeindex_uv_typeno: 'uv',
lifeindex_uv_typenm: '紫外线指数',
lifeindex_uv_attr: '中等',
lifeindex_uv_dese: '涂擦SPF大于15、PA+防晒护肤品。',
lifeindex_xt_id: '147',
lifeindex_xt_typeno: 'xt',
lifeindex_xt_typenm: '血糖指数',
lifeindex_xt_attr: '易波动',
lifeindex_xt_dese: '气温多变,血糖易波动,请注意监测。',
lifeindex_ct_id: '121',
lifeindex_ct_typeno: 'ct',
lifeindex_ct_typenm: '穿衣指数',
lifeindex_ct_attr: '炎热',
lifeindex_ct_dese: '建议穿短衫、短裤等清凉夏季服装。',
lifeindex_xc_id: '104',
lifeindex_xc_typeno: 'xc',
lifeindex_xc_typenm: '洗车指数',
lifeindex_xc_attr: '较不宜',
lifeindex_xc_dese: '风力较大,洗车后会蒙上灰尘。',
lifeindex_kq_id: '106',
lifeindex_kq_typeno: 'kq',
lifeindex_kq_typenm: '空气污染扩散指数',
lifeindex_kq_attr: '中',
lifeindex_kq_dese: '易感人群应适当减少室外活动。' },
{ weaid: '1',
days: '',
week_1: '',
simcode: 'beijing',
citynm: '北京',
cityid: '101010100',
lifeindex_uv_id: '107',
lifeindex_uv_typeno: 'uv',
lifeindex_uv_typenm: '紫外线指数',
lifeindex_uv_attr: '中等',
lifeindex_uv_dese: '涂擦SPF大于15、PA+防晒护肤品。',
lifeindex_xt_id: '147',
lifeindex_xt_typeno: 'xt',
lifeindex_xt_typenm: '血糖指数',
lifeindex_xt_attr: '易波动',
lifeindex_xt_dese: '气温多变,血糖易波动,请注意监测。',
lifeindex_ct_id: '121',
lifeindex_ct_typeno: 'ct',
lifeindex_ct_typenm: '穿衣指数',
lifeindex_ct_attr: '炎热',
lifeindex_ct_dese: '建议穿短衫、短裤等清凉夏季服装。',
lifeindex_xc_id: '149',
lifeindex_xc_typeno: 'xc',
lifeindex_xc_typenm: '洗车指数',
lifeindex_xc_attr: '适宜',
lifeindex_xc_dese: '天气较好,适合擦洗汽车。',
lifeindex_kq_id: '106',
lifeindex_kq_typeno: 'kq',
lifeindex_kq_typenm: '空气污染扩散指数',
lifeindex_kq_attr: '中',
lifeindex_kq_dese: '易感人群应适当减少室外活动。' },
{ weaid: '1',
days: '',
week_1: '',
simcode: 'beijing',
citynm: '北京',
cityid: '101010100',
lifeindex_uv_id: '107',
lifeindex_uv_typeno: 'uv',
lifeindex_uv_typenm: '紫外线指数',
lifeindex_uv_attr: '中等',
lifeindex_uv_dese: '涂擦SPF大于15、PA+防晒护肤品。',
lifeindex_xt_id: '147',
lifeindex_xt_typeno: 'xt',
lifeindex_xt_typenm: '血糖指数',
lifeindex_xt_attr: '易波动',
lifeindex_xt_dese: '气温多变,血糖易波动,请注意监测。',
lifeindex_ct_id: '121',
lifeindex_ct_typeno: 'ct',
lifeindex_ct_typenm: '穿衣指数',
lifeindex_ct_attr: '炎热',
lifeindex_ct_dese: '建议穿短衫、短裤等清凉夏季服装。',
lifeindex_xc_id: '149',
lifeindex_xc_typeno: 'xc',
lifeindex_xc_typenm: '洗车指数',
lifeindex_xc_attr: '适宜',
lifeindex_xc_dese: '天气较好,适合擦洗汽车。',
lifeindex_kq_id: '106',
lifeindex_kq_typeno: 'kq',
lifeindex_kq_typenm: '空气污染扩散指数',
lifeindex_kq_attr: '中',
lifeindex_kq_dese: '易感人群应适当减少室外活动。' },
{ weaid: '1',
days: '',
week_1: '',
simcode: 'beijing',
citynm: '北京',
cityid: '101010100',
lifeindex_uv_id: '107',
lifeindex_uv_typeno: 'uv',
lifeindex_uv_typenm: '紫外线指数',
lifeindex_uv_attr: '中等',
lifeindex_uv_dese: '涂擦SPF大于15、PA+防晒护肤品。',
lifeindex_xt_id: '147',
lifeindex_xt_typeno: 'xt',
lifeindex_xt_typenm: '血糖指数',
lifeindex_xt_attr: '易波动',
lifeindex_xt_dese: '气温多变,血糖易波动,请注意监测。',
lifeindex_ct_id: '121',
lifeindex_ct_typeno: 'ct',
lifeindex_ct_typenm: '穿衣指数',
lifeindex_ct_attr: '炎热',
lifeindex_ct_dese: '建议穿短衫、短裤等清凉夏季服装。',
lifeindex_xc_id: '149',
lifeindex_xc_typeno: 'xc',
lifeindex_xc_typenm: '洗车指数',
lifeindex_xc_attr: '适宜',
lifeindex_xc_dese: '天气较好,适合擦洗汽车。',
lifeindex_kq_id: '106',
lifeindex_kq_typeno: 'kq',
lifeindex_kq_typenm: '空气污染扩散指数',
lifeindex_kq_attr: '中',
lifeindex_kq_dese: '易感人群应适当减少室外活动。' } ] }
后端服务器有两种类型
- web服务器【 静态服务器 】
- api服务器 【 暴露接口 】
请求头部报文
-
1. general 请求基本信息
-
2. response Headers 响应头
-
3. request Headers 请求头
-
4. 携带参数
query string paramters get请求
form data post 请求
WEB静态服务器
const http = require('http'); //引入http
const host = '10.31.158.80'; //域名
const port = 8000; //端口
http.createServer((request, response) => {
response.writeHead(200, { //状态码 请求头
'Content-type': 'text/html;charset=utf8'
})
//内容
response.write('<h1>这里是Nodejs创建的一个静态服务器</h1>');
//告诉前段信息已经结束了
response.end()
}).listen(port, host, () => {
//这是运行在http://xxx上的服务器
console.log(`The server is Runing at:http://${host}:${port}`)
})
$ node http-server.js
The server is Runing at:http://10.31.158.80:8000
引入第三方类库爬数据
http模块
- 爬虫
- 去某一个网站爬取一段数据 -> 数据清洗 -> 后端服务器 -> 发送前端 -> 渲染 数据
- 不是所有网站都可以爬取
- 反爬虫
- 爬虫: 后端渲染的网站
Node.js中event模块
Node.js中 事件的发布 + 事件的订阅 表示一个任务的执行
const Events = require('events');
const fs = require('fs');
const http = require('http');
const host = '10.31.158.80';
const port = 8000;
class myEvent extends Events {} //类的继承
const myevent = new myEvent() //实例化类得到一个实例
//console.log(myevent)
//事件的发布
//myevent.on (事件的名称,事件的回调函数)
myevent.on('a', function() {
http.createServer((req, res) => {
res.writeHead(200, {
'content-type': 'text/html;charset=utf8'
})
//1步
fs.readFile('./1.txt', 'utf8', (error, docs) => {
res.write(`<h3>${docs}</h3>`)
res.end()
})
//2步
// why? 错误?
// res.end()
}).listen(port, host, () => {
console.log(`服务器运行在:http://${host}:${port}`)
})
}) //事件的订阅
//myevent.emit (事件名称)
myevent.emit('a')
api服务器
Node.js中api服务器的创建,我们使用一个第三方库 express
后端解决跨域问题:
1. 设置请求头
2. 使用中间件
const express = require('express');
const app = express() //得到一个对象
const port = 8000;
const host = '10.31.158.80';
//创建接口
app.get('/user', (req, res, next) => { //回调函数我们称之为: 中间件 具有特定功能的一个函数
console.log(req.headers.origin)
res.setHeader('Access-Control-Allow-Origin', '*'); // 设置请求头跨域
res.json({
id: 1,
name: 'zhangsan',
class: '1905'
})
})
app.get('/demo', (req, res, next) => { //回调函数我们称之为: 中间件 具有特定功能的一个函数
console.log(req.headers.origin)
res.setHeader('Access-Control-Allow-Origin', '*'); // 设置请求头跨域
res.json({
id: 1,
name: 'zhangsan',
class: '1905'
})
})
// 创建api服务器,并监听这个服务器
app.listen(port, host, () => {
console.log(`服务器运行在http://${host}:${port}`)
})
使用第三方的包一次性结果所有跨域问题
第三方的包 cors
const express = require( 'express' )
const app = express() // 得到一个app对象
const port = 3000
const host = 'localhost'
const cors = require( 'cors' )//引入第三方的包
// 创建接口
//第三方的包
app.use(cors({
"origin": "*",
"methods": "GET,HEAD,PUT,PATCH,POST,DELETE",
"preflightContinue": false,
"optionsSuccessStatus": 200
}))
app.get( '/user', ( req,res,next ) => { // 回调函数我们称之为: 中间件 具有特定功能的一个函数
res.json({
id: 1,
name: 'zhangsan',
class: '1905'
})
})
app.get( '/demo', ( req,res,next ) => { // 回调函数我们称之为: 中间件 具有特定功能的一个函数
res.json({
id: 2,
name: 'zhangsan',
class: '1905'
})
})
// 创建api服务器,并监听这个服务器
app.listen( port,host,() => {
console.log( `The server is running at : http://${ host }:${ port }` )
})