淘先锋技术网

首页 1 2 3 4 5 6 7

概述

Node.js 可以做什么?

  • 轻量级、高性能的web服务
  • 前后端Javascript同构开发
  • 便捷高效的前端工程化

学习目标

Node.js的架构和运行过程

Node.js的异步IO和事件驱动

Node.js的单线程

Node.js实现API服务

Nodejs核心模块及API使用

1. Nodejs的架构

首先最上层的内置核心模块,在这一层是暴露了相应的JS功能接口,提供开发者直接调用

中间层是找到对应c++功能实现的 Bindings ,是需要v8引擎配合实现

最下层是v8引擎除了构建node的运行环境,负责js代码的最终执行,libuv负责具体node环境下node的细节
在这里插入图片描述
Natives modules

  • 当前层内容由JS实现
  • 提供应用程序可直接调用库,例如FS、path、http等
  • JS语言无法直接操作底层硬件设置

Builtin modules "胶水层"

由c++代码进行编写中间层,实现具体的操作模块,例如socket,http,etc等基础功能

这些相关的不是具体功能,而是调用c++封装而成的

V8 和功能模块

在这里插入图片描述
底层

  • V8: 执行JS代码,提供桥梁接口
  • Libuv: 事件循环、事件队列、异步IO
  • 第三方模块: zlib、http、c-ares等

在这里插入图片描述

为什么是Node.js

Node.js是高性能的web服务器,后来慢慢演化为一门服务端语言

Node不仅仅是一种语言,而且是平台。运行时,对于前端可以是构建服务端的语言

在这里插入图片描述
IO是计算机操作过程中最缓慢的环节

如果是串行模式,对于服务器来说,如果当前处理的是一个长时间等待的IO行为,后续任务不能及时响应,大多的服务端运行高级语言并发处理能力大多采用多线程,多进程方式
但是这种解决方式在一些情境下会有问题,多线程思路是多个任务进程或者线程,开启多个任务,进行任务处理,等待结果
但是如果是多个任务下,就会出现无响应问题
真的无响应,出现Reactor模式,单线程完成多线程工作,不会堵塞

Node.js就是应用了Reactor模式下实现异步IO、事件驱动
单线程、通过异步非阻塞IO来更好的使用CPU资源,实现高并发请求的处理
Node.js更适合用于IO密集高并发请求

Node.js异步IO

对于系统。IO分为阻塞、非阻塞两种
阻塞IO: 重复调用IO操作,判断是否IO结束,就是轮询的方式
常见的轮询技术:read。select、poll、kqueue、event ports

期望实现无需主动判断的非阻塞IO
就是libuv库,根据当前平台判断,依据平台调用响应的异步IO处理方法

Node实现异步IO过程
在这里插入图片描述

异步IO总结

  • IO是应用程序的瓶颈所在
  • 异步IO提供性能无采用原地等待结果返回
  • IO操作属于操作系统级别,平台都有对应的实现
  • Node.js单线程配合事件驱动架构及libuv实现异步 IO

事件驱动架构

事件驱动架构是软件开发的通用模式

事件驱动、发布订阅、观察者
主题发布消息,其他实例接收消息

在这里插入图片描述
基础的事件执行架构

const EventEmitter = require('events')

const myEvent = new EventEmitter()

myEvent.on('事件1', () => {
  console.log('事件1执行了')
})

myEvent.on('事件1', () => {
  console.log('事件1-2执行了')
})

myEvent.emit('事件1')
event模块,执行就是普通的订阅发布模式
通过event注册事件,订阅,触发事件

node 执行这个文件名

Node单线程

Node.js的代表性
使用JS实现高效可伸缩的高性能web服务

单线程如何实现高并发?

Node底层通过异步非阻塞IO配合事件回调通知
注意:Node.js主线程是单线程,不代表Node.js只可以单线程
libuv:分为网络IO、非网络IO、非IO的异步操作

代码演示
单线程在耗时操作的影响

const http = require('http')

function sleepTime (time) {
  const sleep = Date.now() + time * 1000
  while(Date.now() < sleep) {}
  return 
}
sleepTime(4)
const server = http.createServer((req, res) => {
  res.end('server starting......')
})

server.listen(8080, () => {
  console.log('服务启动了')
})

Node.js的应用场景

IO密集型的并发请求

Node.js作为中间层

在这里插入图片描述
操作数据库提供API服务
实时聊天应用程序
AJAX重复的单页应用
Node应用于前端工程化

Node.js实现API服务

通过Node + ts + express 实现一个api服务,体验node对于前端的功能

  1. 创建文件夹,进入执行 npm init -y
  2. npm i typescript
  3. tsc --init 生成tsconfig.json
  4. 创建api_server.ts
  5. npm i ts-node -D
  6. 安装express npm i express

api_server.ts

// 需求:希望有一个服务,可以依据请求的接口内容返回相应的数据
import express from 'express'
import { DataStore } from './data'

// console.log(DataStore.list)

const app = express()

app.get('/', (req, res) => {
  // res.end('1122')
  res.json(DataStore.list)
})

app.listen(8080, () => {
  console.log('服务已经开启了')
})

data.ts

import list from './list.json'

export class DataStore {
  static list = list
}

list.json

[
  {
    "name": "zce",
    "age": 38
  },
  {
    "name": "syy",
    "age": 18
  }
]

Node.js全局对象

全局对象
  • 与浏览器平台的window不完全相同
  • Nodejs全局对象上挂载许多属性

全局对象是JS中的特殊对象
Nodejs全局对象是global
Global的根本作用就是作为宿主
全局对象可以看做是全局变量的宿主

常见的全局变量

__filename: 返回正在执行脚本文件的决定路径
__dirname: 返回正在执行脚本所在目录
timer类函数: 执行顺序与实践循环间的关系
process: 提供与当前进程互动的接口
require:实现模块加载
module、exports:处理模块的导出

// console.log(global)

/* console.log(__filename)
console.log(__dirname)

console.log(this)
 */
// 默认情况 this 是空对象,和 global 并不是一样的

console.log(this == global)

(function () {
  console.log(this == global)
})()

/* require('module')
__filename
__dirname
module 
exports  */

全局变量

无需require,可直接使用
// 1 资源: cpu 内存
// console.log(process.memoryUsage())
// console.log(process.cpuUsage())

// 2 运行环境:运行目录、node环境、cpu架构、用户环境、系统平台
/* console.log(process.cwd())
console.log(process.version)
// console.log(process.versions)
console.log(process.arch)
console.log(process.env.NODE_ENV)
// console.log(process.env.PATH)
console.log(process.env.USERPROFILE)  // HOME
console.log(process.platform) */

// 3 运行状态: 启动参数、PID、运行时间
/* console.log(process.argv)
console.log(process.argv0)  // execArgv
console.log(process.pid) */  // ppid 

setTimeout(() => {
  console.log(process.uptime())
}, 3000)