# 基本
- node 是基于事件驱动的异步操作架构,内置events
- 用到的很多内置模块其实都继承了 eventemitter
# Event Loop
会另外花个篇幅去讲
# 总图
- 同步代码,遇到异步就放进对应的队列
- 同步完成先执行微任务如
promise
,微任务清空就去事件队列 - 这些为事件队列
timers
-pending callback
-idle
,prepare
-poll
-check
-close callbacks
- backtotimers
- 事件队列每次切换都回去清空一次微任务
# 微任务
- 不是队列,有优先级
- promise
- process.nexttick 高于 promise (no why)
# 事件队列说明
timers
执行settimeout/setinterval回调pending callback
操作系统的回调 tcp/udpidle
,prepare
系统内部poll
i/o相关check
setimmediateclose callbacks
执行与close事件的回调
# 异步io
- 阻塞io/非阻塞io,底层会重复(轮询)调用io操作确认io是否结束,对于代码还是同步
- 期望 无需要主动判断的非阻塞io
# libuv
- 几种不同的异步io实现方式的抽象封装层
- 运行->libuv->根据平台去调用底层
- 里面有线程池
- node运行-异步部分-
event loop
-io处理-底层io接口-事件队列(event queue)-event loop
- 其实还是应用异步循环机制加进去
# 事件
- 通过回调的方式走事件驱动
- on/emit/once/off
const eventemitter = require('events')
const myevent = new eventemitter()
myevent.on('yiki1'),()=>{
...
}
myevent.on('yiki1'),()=>{ // 可以多个同名,按照注册顺序
...
}
myevent.emit('yiki1')
# http
const http = require('http')
const serve = http.creatserver(req,res=>{
res.send(..)
let {pathname,query} = url.parse(req.url,true)
// req.header
// req.method
})
serve.listen(9999,()=>{
...
})
# node的高并发
- 主线程是单线程
- 异步非阻塞io配合事件回调通知去实现
- libuv库里面有很多处理线程和线程池帮助实现高并发
# express
import express from 'express'
const app = express()
app.get('/eee/,(req,res)=>{
return sth
})
app.listen(9999,(req,res)=>{
res.end('de')
...
})
# globle
全局对象
- __filename 绝对路径
- __dirname 正在执行脚本所在目录
- timer类
- process 和当前进程进行互动
- require 是拷贝
- module、exports
# process
- version
- arch
- platform
- pid
- on/before/stdout
process.on('exit',(code)=>{
...只能同步
})
process.on('before',(code)=>{
... 异步+同步,但是写异步会不断循环
})
process.exit()
// 重写log
console.log = function(data){
process.stdout.write('----'+data)
}
# pipe
process.stdin.pipe(process.stdout)
// 控制台输入什么就重复什么
# path
内置,用require,资源路径拼接
- resolve(from,to) 返回绝对路径
- pasre() 解析
- format() 序列号路径
- normalize() 规范化路径
- join
# buffer
缓冲区,操作二进制,stream(可以用pipe)
- alloc 指定字节的buffer
- from 接收数据来创建buffer
- fill
- write 写入
- tostring 从里面提取
- slice 截取
- concat
# fs
提供文件系统操作的api,内置,操作文件里面的二进制数据
- readfile 配合path.resolve
- writefile
- appendfile
- copyfile
- watchfile
- open 大文件用 利用buffer
- write 配合open边读边写
- close
# md转html
- 样式/第三方包/占位符
- 读取md+css替换html里面的占位符
- 监听 md 变化,更新html
const fs = require('fs')
const path = require('path')
const marked = require('marked')
const name = require('browser-sync') // 实时显示html
const temp = `html+{{占位符}}`
let mypath = path.join(__dirname, process.argv[2])
let csspath = path.resolve('xx.css')
let htmlpath = mypath.replace(path.extname(mypath),'.html')
// 监听
fs.watchfile(mypath,(curr,prev)=>{
//判断是否一致
if(curr.mtime!==prev.mtime){
fs.readfile(mdpath,'utf-8',(err,data)=>{
let htmlstr = marked(data)
fs.readfile(csspath,'utf-8',(err,data)=>{
let rethtml = temp.repalce('{{content}}',htmlstr).repalce({{style}},data)
fs.writefile(htmlpath,retphtml,err=>{
//success
})
})
})}
})
browsersync.init({
brower:'',
server:__dirname,
watch:true,
init
})
# 定位顺序
- .js-.json-.node/index
# vm
- 创建独立运行的沙箱环境,拿来运行不是js代码的东西
- 内置,require('vm')
- fs + eval , 不能重名
- new function
- 用vm沙箱 ,能拿到全局变量
vm.runinthiscontext(content)
# 发布订阅模式
- 回调嵌套垃圾
- 存在一个调度中心,观察者模式里面是没有的
- 状态发生改变的时候不是发布者去主动通知的,而是通过调度中心去做的
- 订阅者n个 - 想监听的事件注册到-> 消息调度中心(event loop) <-发布者
class pubsub{
constructor(){
this._events = {}
}
// 注册
subscribe(event, callback){
if(this._event[event]){
this._events[event].push(callback)
}else{
this.events[ecent]= [callback]
}
}
publich(event,...args){
const items = this._events[event]
if(items&&item.length){
items.foreach(function(callback){
callback.call(this,...args)
})
}
}
}
let ps = new pubsub()
ps.subscribe('yiki',()=>{
//注册不执行
})
ps.publich('yiki')// 执行
# net 网络通信
- listening
- connection
- close
- error
- data 可读流拿数据操作
- write 在socket上发送数据
- end socket发送fin包
# tcp连接
双工流
- server
const net = require('net')
const server = net.createserver()
const port = 1223
server.listen(port,host)
server.on('listening',()=>{
console.log('server is starting..')
})
server.on('connnetion',(socket)=>{
socket.on('data',(chunk)=>{
const msg = chunk.tostring()
socket.write(buffer.from('hi'))
})
})
- client
const net = require('net')
const client = net.creatconnection({
port:1223
host:
})
client.on('connect',()=>{
client.write('test')
})
# 数据粘包
用settimeout