前端面试题-nodejs

1.什么是nodejs,它与传统的网页服务器有什么不同?

是什么?nodejs是基于Chrome V8引擎的JavaScript运行环境,它可以使JavaScript代码在服务器上运行。

有什么不同?第一,nodejs采用事件驱动、非阻塞式I/O模型,让其轻量且高效。nodejs在处理大量并发连接时,能够保持高效的性能,因为它不会每个连接都创建新的线程,而是使用单线程处理请求。这种模式降低了系统的开销,提高了整体的吞吐量。第二,nodejs是单线程的,这避免了多线程编程中的一些问题,比如线程间的数据同步和线程管理开销。第三,nodejs具有强大的包管理器npm,这有利于开发者安装和管理第三方模块。

2.nodejs的事件驱动和非阻塞I/O模型是如何工作的?

 事件驱动:nodejs采用事件驱动的编程模式,它通过事件来触发回调函数。当web服务器接收到一个请求时,不会立即处理,而是将请求放到事件队列中。主线程会不断监听事件队列,有新事件触发,就会执行相应的回调函数来处理请求。这可以使nodejs同时处理多个请求。

非阻塞I/O:nodejs使用非阻塞I/O模型,该模型不会每个请求都创建一个新的线程或开启新的事件。相反,当服务器接收到一个请求时,它会立即返回并继续处理其他请求。对于需要执行I/O的操作,如读写文件、网络请求等,nodejs会将其放到一个线程池中进行异步处理。这样,主线程可以继续监听事件队列,而不需要等待I/O操作完成、当I/O操作完成,它会通过事件触发相应的回调函数来处理。

3.nodejs中如何进行错误处理?

1.使用try-catch语句来捕获和处理错误

try {
//可能抛出异常的代码
}catch(err){
//处理错误的代码
}

2.使用回调函数

nodejs的部分API都可以接受回调函数作为最后一个参数,用来处理错误。

fs.readFile('/c:/files/a.txt',function(err,data){
    if(err){
        //处理错误
    }else{
        //处理数据
    }
}

3.使用Promise

getData().then(res => {
    //处理数据
}).catch(err => {
    //处理错误
})

4.async/await

async/await是Promise的语法糖,使异步代码看起来像同步代码

async function fn(){
    try{
       const data = await getData()
    }catch(err){
      //处理错误
    }
}
4.nodejs中事件循环执行流程?

nodejs的事件循环是其核心之一,用于处理非阻塞I/O操作和实现异步编程。事件循环是nodejs单线程特性的关键,事件循环使nodejs能够高效的处理大量的并发请求。

工作原理:

1.初始化,创建三个队列

*        Timer队列:setTimeout、setInterval

*        Poll队列:文件读写、数据库操作、网络请求

*        Check队列:process.nextTick、setImmediate

2.三个队列执行之前,先执行微任务队列,微任务队列执行完成在继续执行事件循环

5.请解释一下Node.js的集群化工作模式?

nodejs的集群化工作模式是利用多核CPU和提升服务器性能的方法。因为nodejs是单线程的,它只能利用一个CPU核心进行工作,所以为了更好的利用多核CPU,nodejs提供了集群模块来创建多个子进程,每个子进程运行在独立的线程上,并独立的处理请求。

在集群化工作模式中,主进程负责管理所有的子进程,子进程可以接收相应客户端请求,并独立的进行处理。

集群化的工作模式,可以提高服务器的吞吐量和响应能力。同时由于每个子进程都是独立的,它们之间不会共享内存或状态,因此可以提高应用程序的稳定性和安全性。

6. 什么是nodejs中的Stream?

nodejs中的Stream(流)是一种处理的数据的方式,可以处理大量数据。Stream可以以流的方式处理数据,而不是一次性加载所有数据到内存中。可读流、可写流、Duplex流(可读和可写)

7.nodejs适合什么应用场景?

适用于构建实时、高并发、基于网络的应用程序,如实时聊天应用、实时数据流应用等。由于nodejs的事件驱动和非阻塞I/0模型,它可以处理大量的并发链接。

8. EventEmitter是什么?怎么用?

EventEmitter:事件发射器,用于对nodejs事件进行统一的管理。

EventEmitter的主要作用是简化事件的创建、订阅、发布等操作,使开发者能够更加方便的处理事件。它通过事件驱动的方式,使得各个模块之间的通信更加灵活和高效。

//events模块中的事件总线
const EventEmitter = require("events")

//创建EventEmitter实例
const emitter = new EventEmitter()

const fn = (...args) => {
    console.log("监听事件",args)
}

//监听事件
emitter.on('aaa',fn)

//发射事件
emitter.emit("aaa",1,2,3)

//取消事件
emitter.off('aaa',fn)
9.手写EventBus?
class EventBus {
        constructor() {
          this.eventObj = {};
          this.calbackId = 0;
        }
// 监听事件
        on(key, calback) {
          if (!this.eventObj[key]) {
            this.eventObj[key] = {};
          }
          const id = this.calbackId++;
          this.eventObj[key][id] = calback;

          return id;
        }
// 发布事件
        emit(key, ...args) {
          const calbackList = this.eventObj[key];

          for (let id in calbackList) {
            const cb = this.eventObj[key][id];
            cb(...args);

            if (id.indexOf("d") > -1) {
              delete this.eventObj[key][id];
            }
          }
        }
// 关闭订阅
        off(key, id) {
          delete this.eventObj[key][id];

          if (!Object.keys(this.eventObj[key]).length) {
            delete this.eventObj[key];
          }
        }
// 发射一次事件
        once(key, calback) {
          if (!this.eventObj[key]) {
            this.eventObj[key] = {};
          }

          const id = "d" + this.calbackId++;
          this.eventObj[key][id] = calback;

          return id;
        }
      }

测试代码 

     const ev = new EventBus();

      ev.once("a", (name) => {
        console.log("once");
      });

      const id = ev.on("a", () => {
        console.log("a执行111");
      });

      ev.on("a", (name, age) => {
        console.log("a执行", name, age);
      });

      ev.on("b", () => {
        console.log("b执行");
      });

      ev.emit("a");
      ev.off("a", id);
      ev.emit("a", 123, 777);
      ev.emit("b");
10.koa与express的区别?

1.启动方式不同。koa使用new Koa(),express使用express()

2.中间件形式。

//express
const express = require("express");

const app = express();

app.post(
  "/login",
  (req, res, next) => {
    console.log(1);
    next();  //执行下一个中间件
  },
  (req, res, next) => {
    console.log(2);
    next();
  },
  (req, res, next) => {
    console.log(3);
  }
);

app.listen(8000, () => {
  console.log("启动成功");
});


//koa
const Koa = require("koa");

const app = new Koa();

app.use((ctx, next) => {
  // 请求对象
  console.log(ctx.request); //koa封装的对象
  console.log(ctx.req); //node封装的对象

  // 响应对象
  console.log(ctx.response); //koa封装的对象
  console.log(ctx.res); //node封装的对象

  console.log(ctx.query); //其他属性
  ctx.body = "hhhh";

  next(); //执行下一个中间件
});

app.listen(8000, () => {
  console.log("启动成功");
});

3.异步处理方式。koa通过Generator和async/await使用同步的写法处理异步。express通过回调函数实现异步。

4.路由和试图。express包含完整的应用程序框架,具有路由、模板等功能。koa只有HTTP模块,路由等需要单独引入。

5.错误处理。express使用回调函数捕获错误。koa使用try-catch捕获。

需要使用更多的内置中间件并且对异步处理有更高的要求,Express可能是一个更好的选择。如果希望有更简洁的代码结构并且享受自定义中间件带来的灵活性,那么Koa可能更适合。

11.npm install敲下命令后的执行流程?
  1. 解析命令,获取模块名。
  2. 查找模块,npm会在npm注册表中查找。注册表是一个存储了所有公开npm模块和其版本信息的仓库。npm会查找指定模块的最新版本并存储到本地缓存中。
  3. 解析依赖,npm解析模块的package.json文件,并获取该模块的依赖列表,然后递归的查找这些依赖模块,并在本地缓存中安装。
  4. 安装依赖,在安装前,会先查找本地缓存,如果有,就使用本地缓存,没有就从npm注册表中下周最新版本的依赖并存储到本地。
  5. 处理全局安装,如果使用-g/--global,npm会将模块安装到全局安装目录中。
12.npm、cnpm、yarn和pnpm的区别和优缺点?

1.npm:nodejs默认的包管理器。安装速度慢。

2.cnpm:淘宝镜像进行安装,速度快;但可能更新不及时。

3.yarn:解决了npm在性能和一致性方面的一些问题。安装速度快。

4.pnpm:通过共享相同的依赖项来减少磁盘空间的占用。硬连接、软连接

13.nodejs中的Buffer是什么?

Buffer主要用来处理二进制数据。在node中主要用来进行网络协议处理、读取文件等。

.....持续更新中 

  • 6
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值