1.node js是什么?
node js 是基于chome v8引擎的javascript运行时(运行环境)
2.1nodejs和前端js的区别
- 语法层面
1.前端js使用js web api
2.nodejs 使用 node api - 应用层面
1.前端js用于网页,在浏览器运行
2.nodejs可用于服务端,如开发web server
3.nodejs也可用于本机,webpack等本机工具
3.nodejs如何调试
1.启动nodejs服务时,使用inspect
2.代码中使用debugger断点
3.使用chrome调试 - chrome://inspect
4.当前文件和当前目录的路径,如何获取
1.__filename
2.__dirname
3.两个都是全局变量
5.commonjs和es6Module的区别
1.es6 Module是静态引入,编译时引入,所以必须放在最外层
2.语法不同
3.commonjs是动态引入,执行时引入
4.es6 module 是静态引入,编译时引入
6.path.resolve和path.join的区别
1.两者都是用于拼接文件路径
2.path.resolve获取绝对路径
3.path.join获取相对路径
7.时间循环event loop 在nodejs和浏览器的区别
- nodejs中的异步
1.setTimeout setInterval -宏任务
2.Promise async/await -微任务
3.process.nextTick - 微任务(微任务中最先执行)
4.setImmediate - 宏任务
5.I/O文件 网络 - 宏任务
6.Socket连接,如连接mysql - 宏任务 - 基本执行步骤
1.执行同步代码
2.执行微任务
3.执行宏任务,回到第二步 -
nodejs中的异步特点
1.微任务不多
2.宏任务类型较多
3.如果宏任务都放在一个callback Queue中,不好管理
image.png - 每个阶段和微任务
1.每个阶段结束之后,都要执行微任务
2.微任务中,process.nextTick优先级最高,最早执行
3.(但process.nextTick现已不推荐使用,因为会阻塞IO) - 几个细节
1.settimeout比setImmediate执行更早
2.process.nexetTick比promise.then执行更早
3.另外,建议用setImmediate代替process.nextTick - event loop 在浏览器和nodejs的区别
1.nodejs异步api更多,宏任务类型也更多
2.nodejs的event loop分为6各阶段,要按照顺序执行
3.微任务中process.nexetTick优先级更高 - 关于nodejs版本
1.新版nodejs已和浏览器趋同
2.即,兼容代码在两者执行的结果是一样的
3.网上很多资料都是旧版nodejs的,注意鉴别
8.async/await执行顺序问题
9.session如何实现登录?
-
cookie如何实现登录校验
image.png
前端登录完,服务端会设置一个cookie,把用户信息设置上给前端,在同域下,前端在请求其他接口的时候都会带上cookie(会触及到设置cookie的过期时间和安全性问题)
-
session和cookie的关系
image.png
cookie带了用户信息的,用户信息是敏感的,明文的话容易暴露,我们在用户信息里面把用户的标识带上如userId,这样前后端穿的是一个无意义的标识,服务端的session来处理对应标识.cookie是用户身份的记录,session是服务端,存储了记录和用户身份的对应关系.
- session为何需要存储在redis中
1.进程有内存限制
2.进程的内存是相互隔离的
3.存储到redis,可解决这些问题
10.描述koa2和express的中间件机制
1.从代码来看,中间件是一个函数
2.从业务来看,中间件则是一个独立的模块
3.模块拆分,模块流转,即可完成复杂的功能
- express中间件实现
const http = require('http')
const slice = Array.prototype.slice
class LikeExpress {
constructor() {
this.routes = {
all: [],
post: [],
get: []
}
}
register(path) {
let info = {}
if (typeof path === 'string') {
info.path = path
// 从第二个参数开始,转换为数组,存入stack
info.stack = slice.call(arguments, 1) //数组
} else {
info.path = '/'
// 全部存入
info.stack = slice.call(arguments, 0)
}
return info
}
use() {
const info = this.register.apply(this, arguments)
this.routes.all.push(info)
}
post() {
const info = this.register.apply(this, arguments)
this.routes.post.push(info)
}
get() {
const info = this.register.apply(this, arguments)
this.routes.get.push(info)
}
match(method, url) {
let stack = []
if (url === '/favicon.ico') {
return stack
}
// 获取routes
let curRoutes = []
curRoutes = curRoutes.concat(this.routes.all)
curRoutes = curRoutes.concat(this.routes[method])
curRoutes.forEach(routeInfo => {
if (url.indexOf(routeInfo.path) === 0) {
stack = stack.concat(routeInfo.stack)
}
})
return stack
}
// 核心的next机制
handle(req, res, stack) {
const next = () => {
// 拿到第一个匹配的中间件
const middleware = stack.shift()
if (middleware) {
// 执行中间件函数
middleware(req, res, next)
}
}
next()
}
callback() {
return (req, res) => {
res.json = (data) => {
res.setHeader('Content-type', 'application/json')
res.end(
JSON.stringify(data)
)
}
const url = req.url
const method = req.method.toLowerCase()
const resultList = this.match(method, url)
this.handle(req, res, resultList)
}
}
listen(...args) {
const server = http.createServer(this.callback())
server.listen(...args)
}
}
module.exports = () => {
return new LikeExpress()
}
11.读取大文件 - 流 stream
1.1G大小的acess.log
2.分析其中Chrome浏览器的占比
3.考虑cpu和内存的限制
const fs = require('fs')
const path = require('path')
const readline = require('readline')
const filename = path.join(__dirname, '../', '../', 'logs', 'acess.log')
// 创建readStream
const redStream = fs.createReadStream(filename)
// 创建readline对象
const rl = readline.createInterface({
input: redStream
})
// 初始化总访问数据
let num = 0
// 初始化谷歌数据
let chromeNum = 0
// 开始读取
rl.on('line', readData => {
if (!readData) {
return
}
//记录总行数
num++
const arr = readData.split(' -- ')
if (arr[2] && arr[2].indexOf('Chrome') > 0) {
chromeNum++
}
})
rl.on('close', () => {
console.log('chromeNum:' + chromeNum)
console.log('num:' + num)
console.log('Chrome占比:' + chromeNum / num)
})
12.nodejs线上为何开启多进程(PM2)
1.高效使用多核CPU
2.充分利用服务器内存
3.最终:压榨服务器,不浪费资源