10.NodeJS框架

简介: JavaScript采用单线程机制以避免DOM渲染冲突,通过事件循环(Event Loop)实现异步操作。任务队列管理异步事件,主线程执行完同步任务后不断从队列中读取任务。Node.js基于V8和libuv,利用事件驱动处理并发,并通过child_process模块支持多进程。Express和Koa为常用框架,前者基于回调,后者使用async/await与洋葱模型中间件,提升异步控制与错误处理能力。
  1. 为什么JavaScript是单线程?

    防止DOM渲染冲突的问题;

    Html5中的Web Worker可以实现多线程
    2.什么是任务队列?
    任务队列"是一个先进先出的数据结构,排在前面的事件,优先被主线程读取。主线程的读取过程基本上是自动的,只要执行栈一清空,"任务队列"上第一位的事件就自动进入主线程。
    2.1 同步和异步任务
    1
    同步任务指的是,在主线程上排队执行的任务,只有前一个任务执行完毕,才能执行后一个任务;
    2
    异步任务指的是,不进入主线程、而进入"任务队列"(task queue)的任务,只有"任务队列"通知主线程,某个异步任务可以执行了,该任务才会进入主线程执行。
    2.2 执行流程
    1
    所有同步任务都在主线程上执行,形成一个执行栈(execution context stack)。
    2
    主线程之外,还存在一个"任务队列"(task queue)。只要异步任务有了运行结果,就在"任务队列"之中放置一个事件。
    3
    一旦"执行栈"中的所有同步任务执行完毕,系统就会读取"任务队列",看看里面有哪些事件。那些对应的异步任务,于是结束等待状态,进入执行栈,开始执行。
    4
    主线程不断重复上面的第三步。
  2. 什么是事件循环(EventLoop)?
    主线程从"任务队列"中读取事件,这个过程是循环不断的,所以整个的这种运行机制又称为Event Loop(事件循环)。
    3.1 定时器函数的基本使用方法对比?

    setTimeout : 只是将事件插入了"任务队列",必须等到当前代码(执行栈)执行完,主线程才会去执行它指定的回调函数

    process.nextTick : 在当前"执行栈"的尾部----下一次Event Loop(主线程读取"任务队列")之前----触发回调函数。(所有的异步任务被触发之前执行)

    setImmediate:在当前"任务队列"的尾部添加事件,也就是说,它指定的任务总是在下一次Event Loop时执行,这与setTimeout(fn, 0)很像。
    3.2 setImmediate和setTimeout 哪个回调函数先执行呢?
    Note
    上面代码中,setImmediate和setTimeout被封装在一个setImmediate里面,它的运行结果总是1--TIMEOUT FIRED--2,这时函数A一定在timeout前面触发。至于2排在TIMEOUT FIRED的后面(即函数B在timeout后面触发),是因为setImmediate总是将事件注册到下一轮Event Loop,所以函数A和timeout是在同一轮Loop执行,而函数B在下一轮Loop执行。
    3.3 process.nextTick和setImmediate的区别?
    多个process.nextTick语句总是在当前"执行栈"一次执行完,多个setImmediate可能则需要多次loop才能执行完。
  3. 说一下NodeJS的运行机制?
    1
    V8引擎解析JavaScript脚本。
    2
    解析后的代码,调用Node API。
    3
    libuv库负责Node API的执行。它将不同的任务分配给不同的线程,形成一个Event Loop(事件循环),以异步的方式将任务的执行结果返回给V8引擎。
    4
    V8引擎再将结果返回给用户。
  4. Node创建线程的方法和区别?
    5.1 Node的单线程
    1
    Node.js 是以单线程的模式运行的,但它使用的是事件驱动来处理并发,这样有助于我们在多核 cpu 的系统上创建多个子进程,从而提高性能。
    2
    每个子进程总是带有三个流对象:child.stdin, child.stdout 和child.stderr。他们可能会共享父进程的 stdio 流,或者也可以是独立的被导流的流对象。
    3
    Node 提供了 child_process 模块来创建子进程
    5.2 创建进程的方法
    1
    exec - child_process.exec 使用子进程执行命令,缓存子进程的输出,并将子进程的输出以回调函数参数的形式一次性返回。exec方法会从子进程中返回一个完整的buffer。默认情况下,这个buffer的大小应该是200k。如果子进程返回的数据大小超过了200k,程序将会崩溃,同时显示错误信息“Error:maxBuffer exceeded”。你可以通过在exec的可选项中设置一个更大的buffer体积来解决这个问题,但是你不应该这样做,因为exec本来就不是用来返回很多数据的方法。
    2
    spawn - child_process.spawn 使用指定的命令行参数创建新进程。spawn 会返回一个带有stdout和stderr流的对象。你可以通过stdout流来读取子进程返回给Node.js的数据。stdout拥有’data’,’end’以及一般流所具有的事件。当你想要子进程返回大量数据给Node时,比如说图像处理,读取二进制数据等等,你最好使用spawn方法。
    3
    fork - child_process.fork 是 spawn()的特殊形式,用于在子进程中运行的模块,如 fork(‘./son.js’) 相当于 spawn(‘node’, [‘./son.js’]) 。与spawn方法不同的是,fork会在父进程与子进程之间,建立一个通信管道,用于进程之间的通信。
    5.3 实例分析
    5.3.1 exec
    5.3.2 spawn
    5.3.3 fork
    分为 “父进程”(parent.js) 和”子进程”(child.js)。在命令行执行的时候要切换到上述文件的目录中,否则会找不到子进程。
    parent.js
    child.js
  5. 介绍一下express或koa框架的基本架构?
    1
    Express 是一个Node.js的基础框架,主要基于 Connect 中间件,并且自身封装了路由(需要配合bodyParser)、视图处理等功能,使用人数众多,弊端是callback回调方式。
    2
    Koa 是一个比Express更精简,使用node新特性的中间件框架。其提供的是一个架子,而几乎所有的功能都需要由第三方中间件完成,比如koa-router, koa-view等。
    Note
    Koa 利用 co 作为底层运行框架,利用 Generator 的特性,实现“无回调”的异步处理
    6.1 处理路由
    6.1.1 Express
    Note
    使用 express.Router 类来创建可安装的模块化路由处理程序。Router 实例是完整的中间件和路由系统,以下示例将路由器创建为模块,在其中装入中间件,定义一些路由,然后安装在主应用程序的路径中。
    接着,在应用程序中装入路由器模块:
    6.1.2 Koa
    路由处理 Express 是自身集成的,而 Koa 需要引入中间件
    6.2 HTTP Request
    Note
    两个框架都封装了HTTP Request对象,有一点不同是 Koa v1 使用 this 取代 Express 的 req、res。
    6.2.1 Express
    6.2.2 Koa
    6.3 区别
    6.3.1 异步流程控制
    Express 采用 callback 来处理异步,Koa v1 采用 generator,Koa v2 采用 async/await。
    6.3.2 错误处理
    Express 使用 callback 捕获异常,对于深层次的异常捕获不了, Koa 使用 try catch,能更好地解决异常捕获。
    Plain Text
    复制代码
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    // Express callback
    app.use(function (err, req, res, next) {
    console.error(err.stack)
    res.status(500).send('Something broke!')
    })
    // Koa generator
    app.use(function *(next) {
    try {
    yield next
    } catch (err) {
    this.status = err.status || 500
    this.body = { message: err.message }
    this.app.emit('error', err, this)
    }
    })
    // Koa async/await
    app.use(async (ctx, next) => {
    try {
    await next()
    } catch (err) {
    ctx.status = err.status || 500
    ctx.body = { message: err.message }
    ctx.app.emit('error', err, this)
    }
    })
    6.3.3 中间件处理
    1
    Express中app.use就是往中间件数组中塞入新的中间件,中间件处理方式是线性的,next过后继续寻找下一个中间件。 一个请求进来经过一系列中间件处理后再响应给用户,清晰明了。
    2
    缺点:基于 callback 组合业务逻辑,业务逻辑复杂时嵌套过多,异常捕获困难。
    3
    Koa的中间件处理方式是一个洋葱模型,koa处理完中间件后还会回来走一趟,这就给了我们更加大的操作空间。
    Plain Text
    复制代码
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    const Koa = require('koa');
    const app = new Koa();

    // x-response-time
    app.use(async (ctx, next) => {
    const start = Date.now();
    await next();
    const ms = Date.now() - start;
    ctx.set('X-Response-Time', ${ms}ms);
    });

    // logger
    app.use(async (ctx, next) => {
    const start = Date.now();
    await next();
    const ms = Date.now() - start;
    console.log(${ctx.method} ${ctx.url} - ${ms});
    });

    // response
    app.use(async ctx => {
    ctx.body = 'Hello World';
    });
    Note
    当koa处理中间件遇到await next()的时候会暂停当前中间件进而处理下一个中间件,最后再回过头来继续处理剩下的任务

相关文章
|
4月前
|
机器学习/深度学习 存储 知识图谱
知识蒸馏
知识蒸馏是一种模型压缩技术,通过将大模型(教师)的知识迁移到小模型(学生)中,在降低计算成本的同时提升小模型性能。核心思想是让学生模仿教师的输出分布或中间特征。常用方法包括基于软标签的Hinton蒸馏(引入温度提升泛化信息)、特征蒸馏(对齐中间层表示)。按信息访问程度分为黑盒(仅输出)与白盒(含内部结构)。广泛用于加速推理与模型轻量化。
173 0
|
数据库 数据安全/隐私保护 C++
Python并发编程实战:线程(threading)VS进程(multiprocessing),谁才是并发之王?
【7月更文挑战第10天】Python并发对比:线程轻量级,适合I/O密集型任务,但受GIL限制;进程绕过GIL,擅CPU密集型,但通信成本高。选择取决于应用场景,线程利于数据共享,进程利于多核利用。并发无“王者”,灵活运用方为上策。
504 2
|
存储 SQL 关系型数据库
openGauss6.0单点企业版部署_openEuler22.03_x86
openGauss6.0单点企业版部署_openEuler22.03_x86
|
4月前
|
机器学习/深度学习 算法 关系型数据库
强化学习
强化学习(RL)是一种通过智能体与环境交互来学习最优策略的机器学习方法,核心是最大化长期累积奖励。其关键概念包括状态、动作、奖励、策略与价值函数,依赖试错和延迟奖励机制。常用方法有基于值的Q-learning、基于策略的Policy Gradient,以及结合两者的Actor-Critic框架。PPO、DPO等算法在实际中广泛应用,尤其在RLHF中优化语言模型。该领域持续发展,追求高效、稳定与实用的决策智能。
432 0
|
4月前
|
存储 人工智能 NoSQL
RAG技术
RAG(检索增强生成)通过结合外部知识库与大模型,提升回答准确性,缓解知识过时与幻觉问题。核心架构含检索器、生成器与向量数据库,支持密集、混合检索,常用FAISS、Pinecone等工具,广泛应用于问答系统与AI面试场景。(238字)
168 0
|
4月前
|
存储 人工智能 JSON
Agent系统
大模型Agent是具备自主规划、推理、工具调用与记忆能力的智能系统,能分解任务、反思调整并持续交互。核心架构含大脑(LLM)、感知、行动与记忆模块,支持函数调用与多Agent协作,广泛应用于复杂任务场景,区别于传统Chatbot,更具主动性与执行力。
196 0
|
4月前
|
NoSQL Java 数据库连接
第七章 SpringBoot框架
SpringBoot简化了Spring应用开发,核心功能包括:starter起步依赖简化配置、自动配置根据条件加载Bean、内嵌服务器支持jar包运行。通过@SpringBootApplication实现自动化配置,自定义starter可封装通用功能,配置优先级为:命令行参数 > 系统属性 > properties > yml/yaml文件。
330 0
|
4月前
|
自然语言处理
主流大模型结构
本文系统梳理主流大模型架构:Encoder-Decoder(如T5)、Decoder-Only(如GPT)、Encoder-Only(如BERT)和Prefix-Decoder(如GLM),详解GPT、LLaMA及中文模型发展,对比参数、上下文与特性,助力理解架构差异与选型策略,涵盖面试核心要点。
325 0
|
4月前
|
缓存 算法 C++
模型推理加速
大模型推理加速关键技术包括KV-Cache优化、连续批处理、投机解码与模型并行等,涵盖算法、系统与硬件协同优化。vLLM等框架通过PagedAttention提升效率,助力高并发、低延迟场景落地。
255 0