# Node 基础面试题和答案解析

# 1、Node.js 如何工作的 ?

答案解析

Node.js 是一个使用 JavaScript 作为其脚本语言并运行 Chrome 的 V8 JavaScript 引擎的虚拟机。

  • 基本上是 Node.js 基于事件驱动的架构,其中 I/O 异步运行,使其轻量且高效。
  • 它也被用于开发桌面应用程序以及一个名为 electron 的流行框架,因为它提供了 API 来访问 OS(操作系统) 级别的功能,例如文件系统、网络等。

# 2、Node.js 比其他最流行的框架好在哪里 ?

答案解析

  • Node.js 提供了简单的开发,因为它的非阻塞 I/O 和基于偶数的模型导致较短的响应时间和并发处理,这与开发人员必须使用线程管理的其他框架不同。
  • 它运行在 chrome v8 引擎上,该引擎是用 c++ 编写的,并且具有不断改进的高性能。
  • 此外,由于我们将在前端和后端都使用 Javascript,因此开发速度会快得多。
  • 最后,还有充足的库,这样我们就不需要重新发明轮子了

# 3、Node.js 如何克服 I/O 操作阻塞的问题 ?

答案解析

由于 node.js 有一个事件循环,可用于以异步方式处理所有 I/O 操作,而不会阻塞 main 函数。

  • 如果需要进行一些网络调用,它将被安排在事件循环中,而不是主线程(单线程)中。
  • 如果有多个这样的 I/O 调用,每个调用都会相应地排队分别执行(除了主线程)。

因此,即使我们有单线程 JS,I/O 操作也是以非阻塞方式处理的。

# 4、为什么 Node.js 是单线程的 ?

答案解析

Node.js 是作为异步处理的实验显式创建的。
这是为了尝试一种新的理论,即:在单个线程上进行异步处理,而不是通过不同框架进行缩放的现有基于线程的实现。

# 5、如果 Node.js 是单线程的,那么它如何处理并发?

主循环是单线程的,所有异步调用都由 libuv 库管理。

// 应用案例
const crypto = require("crypto");
const start = Date.now();
function logHashTime() {
  crypto.pbkdf2("a", "b", 100000, 512, "sha512", () => {
    console.log("Hash: ", Date.now() - start);
  });
}
logHashTime(); // 输出 1213
logHashTime(); // 输出 1225
logHashTime(); // 输出 1212
logHashTime(); // 输出 1222

// 这是因为 libuv 设置了一个线程池来处理这种并发。线程池中有多少线程取决于内核数量,但您可以覆盖它。

# 6、Node.js 中有多少种 API 函数 ?

答案解析

有两种类型的 API 函数:

  • 异步、非阻塞函数:主要是 I/O 操作,可以从主循环中分叉出来。
  • 同步的、阻塞的函数 :主要是影响在主循环中运行的进程的操作。

# 7、你是如何管理 Node.js 项目中的包 ?

答案解析

它可以由许多软件包安装程序及其相应的配置文件进行管理。

  • 其中大多使用 npm 或 yarn。两者都提供了几乎所有的 javascript 库,具有控制特定环境配置的扩展功能。
  • 为了维护项目中安装的库版本,我们使用 package.json 和 package-lock.json 以便将该应用程序移植到不同的环境中没有问题。

# 8、Node.js 有哪些常用的计时特性 ?

答案解析

  • setTimeout/clearTimeout 这用于实现代码执行的延迟。
  • setInterval/clearInterval 这用于多次运行代码块。
  • setImmediate/clearImmediate 作为 setImmediate() 参数传递的任何函数都是 在事件循环的下一次迭代中执行的回调。
  • process.nextTick setImmediate 和 process.nextTick 似乎都在做同样的事情。但,你可能更喜欢其中之一,这取决于回调函数的紧迫性。

# 9、使用 Promise 代替回调有什么好处 ?

答案解析

  • 使用 Promise 的主要优点是您可以获得一个对象来决定异步任务完成后需要采取的操作。
  • 这提供了更易于管理的代码并避免了回调地狱。

# 10、Node.js 中的 fork 是什么 ?

答案解析

  • 通常,fork 用于生成子进程。
  • 在 node 中,它用于创建一个新的 v8 引擎实例来运行多个 worker 来执行代码。

# 11、module.exports 的用途是什么 ?

答案解析

  • 这用于公开要在项目其他地方使用的特定模块或文件的功能。
  • 也可用于将所有类似功能封装在一个文件中,从而进一步改进项目结构。

例如,您有一个包含所有 utils 函数的文件,使用 util 来获取问题陈述的不同编程语言的解决方案。

const getSolutionInJavaScript = async ({
 problem_id
}) => {
...
};
const getSolutionInPython = async ({
 problem_id
}) => {
...
};
module.exports = { getSolutionInJavaScript, getSolutionInPython }

因此使用 module.exports 我们可以在其他文件中使用这些函数:

const { getSolutionInJavaScript, getSolutionInPython } = require("./utils");

# 12、可以使用哪些工具来确保代码风格一致 ?

答案解析

ESLint 可以与任何 IDE 一起使用,以确保一致的编码风格,这进一步有助于维护代码库。

# 13、你对回调地狱的理解是什么 ?

async_A(function(){
   async_B(function(){
       async_C(function(){
           async_D(function(){
           ....
           });
       });
   });
});

对于上面的示例,我们正在传递回调函数,它使代码不可读且不可维护。

因此我们应该更改异步逻辑以避免这种情况。

# 14、Node.JS 中的事件循环是什么 ?

答案解析

但凡异步函数,都由事件循环使用队列和侦听器进行管理。我们可以使用下图得到这个想法:

image-20220518220457351

因此,当需要执行异步函数(或 I/O)时,主线程会将其发送到另一个线程,从而允许 v8 继续执行主代码。

  • 事件循环涉及不同阶段的特定任务,例如计时器、挂起的回调、空闲或准备、轮询、检查、使用不同的 FIFO 队列关闭回调。
  • 此外,在迭代之间,它会检查异步 I/O 或计时器,如果没有异步 I/O 或计时器,则会完全关闭。
上次更新时间: 6/8/2023, 9:23:17 PM

大厂最新技术学习分享群

大厂最新技术学习分享群

微信扫一扫进群,获取资料

X