Node.js 入门你需要知道的 10 个问题

图片描述

本文为您分享「Node.js 入门你需要知道的 10 个问题」这些问题可能也是面试中会被问到的,当然问题不仅仅是这 10 道,因此,最近开源了一个新项目 Nodejs-Interview-Questions 专注于 Node.js 面试题的分享,提供了中英文版本,您也可以在线预览: https://interview.nodejs.red/

Q1: 什么是 Node.js?

Node.js 是一个基于 Chrome V8 引擎的 JavaScript 运行环境。它是一个开源和跨平台的服务端应用程序。任何人都可以编写 JavaScript 代码来开发 Node.js 应用程序。它可以运行于 Microsoft Windows、Linux、 或 OS 系统。

Node.js 不是一个新的语言,也不仅仅是一个基于 JavaScript 的框架,它基于 Chrome 的 JavaScript 运行时,因此代码的编写和执行与浏览器非常相似。

Node.js 功能

以下是 Node.js 的一些重要功能

  • 高度可扩展

Node.js 使用的单线程模型且采用了事件循环架构,使得编写可扩展性高的服务器变得既容易又安全。一些传统的服务端语言会创建多线程来处理请求,通常创建线程都是有系统资源开销的,因此也会有一些限制,而 Node.js 只创建一个线程来处理更多的请求。

  • 事件驱动和异步

Node.js 的所有 API 都是异步的。这意味着下一个请求来临时可以直接处理而不用等待上一次的请求结果先返回。

  • No Buffering

Node.js 从不缓冲任何任何数据,参见What is No-Buffering feature of Node.js

我们许多人可能会对 Node.js 感到困惑。它不是像 Apache 这样的 Web 服务器。Node.js 提供了一种新方法来执行我们的代码。它是 JavaScript 的运行时。Node.js 提供了创建 HTTP 服务器的方法,我们可以在这之上托管我们的应用程序。

Source: Introduction To Node.js

Q2: 如何安装 Node.js?

我们可以从 Node.js 官方网站 https://nodejs.org/en/ 下载安装软件。

nvm 安装

这里推荐您使用 nvm 工具安装,方便后期的升级进行 Node.js 版本管理,以下为安装步骤:

验证安装结果

在 Node.js 安装成功之后,我们可以检查它是否正常工作。

打开命令终端,输入以下命令

$ node

之后将出现 Node 提示符,我们写入以下命令,运行查看

console.log("hello world!");   

按 Enter 键

图片描述

Q3: 如何用 Node.js 监听 80 端口?

这是有陷阱的,在类似一些 Unix 系统中你不应该尝试监听 80 端口,这么做你需要拥有超级用户权限,因此,不推荐你这么做。

尽管如此,如果你一定要让应用监听 80 端口,可以使用 Nginx 来实现,在应用前方加上一层反向代理。还是建议你监听大于 1024 的端口。

Q4: 什么是错误优先的回调函数?

错误优先回调函数用于同时返回错误(error)和数据信息(data),返回值的第一个参数做为错误信息描述,并且验证它是否出错(非错 error 为 null),其它参数用于返回数据。

fs.readFile(filePath, function(err, data) {  
  if (err) {
    // 错误信息处理
    return console.log(err)
  }
  
  // return the data object
  return data;
})

Q5: 你可以在 Node.js 中创建 Http 服务吗?通过代码来展示

在 Node.js 中创建一个 Http 服务是很简单的一件事情,我们可以通过 HTTP 模块来完成这些操作。

const http = require('http');
const server = http.createServer((request, response) => {
    if (request.url === '/hello')  {
        response.writeHead(200, {
            'Content-Type': 'text/plain',
        });
        response.end('hello world!');
    } else {
        response.end('OK!');
    }
});

server.listen(3000, '127.0.0.1', () => {
    console.log('service is listening at http://127.0.0.1:3000');
});

Q6: Node.js 的核心组件有哪些?

Node.js 的核心组建是系统 API、V8 引擎和 Libuv。

Libuv 库

libuv 库是一个跨平台的支持事件驱动的 I/O 库。它是使用 C 和 C++ 语言为 Node.js 所开发的。但是它也被应用于 Mozilla's 的 Rust、Luvit、Julia、pyuv 等其它的语言。

libuv 库是 I/O 操作的核心部分,例如读取文件和 OS 交互。

关于 Libuv 的学习,可以参考 libuv中文教程

V8 引擎

来自于谷歌:“V8 是谷歌开源的高性能 JavaScript 引擎”,使用 C++ 开发,并在谷歌浏览器中使用。V8 中实现的 ECMAScript 中指定 ECMA - 262 ,第 3版运行在 Windows XP 和 Vista、Mac OS X 的 10.5 和 Linux 系统使用 IA - 32 或 ARM/MIPS 处理器。V8 可以独立运行,也可以嵌入到任何 C++ 应用程序。

如果你感兴趣想学习更多的 V8 引擎,请访问 What is V8?

APIs (NodeJS Core Libs)

Node.js APIs 是根据您的请求去调用一些函数执行一些业务操作。默认情况下 Node.js 的 APIs 都是异步的,但是你想同步使用也是可以的(同步方式是不推荐的)。

例如,这个 fs 模块可以使用同步方式也可以使用异步方式。

var fs = require('fs');  
fs.readFile('/files/help.txt', function(err, buf) {  
    // use fs.readFileSync() for sync operation. console.log(buf.toString());  
});   

Source: Introduction to NodeJS, A SSJS: Part I - Components Explained

Q7: 什么是“回调地狱”及如何避免它?

“回调地狱”是指严重的回调嵌套,这些回调嵌套使得代码变得难以阅读和维护。

以下是回调嵌套的示例:

query("SELECT clientId FROM clients WHERE clientName='picanteverde';", function(id){
  query(`SELECT * FROM transactions WHERE clientId=${id}`, function(transactions){
    transactions.each((transac) => {
      query(`UPDATE transactions SET value = ${transac.value*0.1} WHERE id=${transac.id}`, (error) => {
        if(!error){
          console.log("success!!");
        }else{
          console.log("error");
        }
      });
    });
  });
});

在某种程度上,修复“回调地狱”的方式是模块化。回调被分解为独立的函数,这些函数可以通过参数进行传递。所以,针对以上代码的第一个改进如下所示:

const logError = (error) => {
    if(!error){
      console.log("success!!");
    }else{
      console.log("error");
    }
},
  updateTransaction = (t) => {
    query(`UPDATE transactions SET value = ${t.value*0.1} WHERE id=${t.id}`, logError);
},
  handleTransactions = (transactions) => {
    transactions.each(updateTransaction);
},
  handleClient = (id) => {
    query(`SELECT * FROM transactions WHERE clientId=${id}`, handleTransactions);
};

query("SELECT clientId FROM clients WHERE clientName='picanteverde';",handleClient);

尽管这个代码相比第一个示例更容易易读,而且我们创建的的函数还可以得到复用。但是在某些情况下,我们想要使程序更健壮可通过 Promise 来解决。

此外,generators 也提供了强大的回调地狱解决方案,使用它可以解决不同回调之间的依赖关系。然而 generators 会更高级一些使用起来会复杂一些。关于 Generators 更多信息可以阅读这篇文章 Generators in Node.js

然而,以上的虽然能很好解决回调地狱问题,但是目前有了更好的方案 Async/Await。使用 Async/Await 需要注意 Node.js 版本要在 v7.5 版本之上。

Source: 8 Essential Node.js Interview Questions

Q8: 什么是 Node.js 的事件驱动编程?

事件驱动程序是由事件(click、load 等)决定的代码流程术语。它是当今流行编程语言(例如 C#、Java)里一个最基本的里程碑,在这里不会详细讲述。在 Node.js 中或者一些其它类型的 JavaScript 项目中,我们都在使用事件驱动编程。也许你并不知道事件驱动编程,但是在一些页面加载或按钮单击事件中,你已经在使用了。

举一个典型的事件驱动流程的例子,看下它是如何在 Node.js 中完成中:

result = getJSONfromDestination();  
binddata(result);  

上述操作是一个阻塞 I/O(单线程模式下将会等待这个阻塞 I/O 完成之后才会进行下一步)

现在让我们看看异步方式该如何进行(非阻塞 I/O 进程)

json_finished = function(result){  
    binddata(result);  
}  
  
getJSONfromDestination(jsonfinished); 

如上所示,这是一个非阻塞的例子,因为 json_finished 不是你所想向的那样会直接工作。当您调用 getJSONfromDestination 函数并将 jsonfinished 做为参数传递时,它才开始工作。

Source: NodeJS Series #6: Event - Driven Programming

Q9: 什么是 NPM? 在 Node.js 中什么时候需要 NPM?

NPM 是 Node.js 中的包管理器。允许我们为 Node.js 安装各种模块,这个包管理器为我们提供了安装、删除等其它命令来管理模块。这里有一点我们需要注意,我们必须要有一个 package.json 文件或 node_modules 目录安装模块到本地。

NPM 最好的一点是它会在本地存储我们所安装的依赖项,存在于 package.json 的 dependencies 对象里。例如,如果一个模块 X 使用了模块 A 版本为 1.0,模块 Y 使用了模块 A 版本为 1.5,那么模块 X 或 Y 都将在本地拥有自己对应的模块 A 的副本。

// 模块 X
{
  "name": "X",
  "dependencies": {
    "A": "^1.0"
  }
}
// 模块 Y
{
  "name": "Y",
  "dependencies": {
    "A": "^1.5"
  }
}

需要 NPM 包

当我们在开发一些 Node.js 项目时,可能会遇到一些地方需要 NPM,例如链接 Redis、MongoDB 或者发送请求 Request 等,有了这些模块可以使我们更专注于业务开发,当然有时你会有些特别的需求,这时可能需要自己去封装一个 NPM 模块,实现复用。

点击下面 Source 阅读更多关于 NPM 的相关内容

Source: How to Create Nodejs Module and Publish Over to Npm

Q10: Node.js 可以做什么? 10 个 Node.js 的应用场景?

Node.js 可以做 Web 服务端、命令行工具 (Java, PHP 可以做的 JS 也可以做),现在让我们看下 Node.js 的 10 个应用场景:

  1. Web 开发: Express + EJS + MongoDB(mongoose)/Mysql
  2. REST 开发: Restify
  3. IM 即时聊天: Express + Socket.io
  4. 网络爬虫: Cheerio/request
  5. 博客系统: Hexo
  6. 网络论坛: Nodeclub
  7. Web 幻灯片: Cleaver
  8. 前端构建工具: bower.js
  9. OAuth 认证: Passport
  10. 定时任务工具: Later

Source: What does node. js do? 10 application scenarios for node. js

本片文章首发于慕课网:https://www.imooc.com/article/289202

阅读推荐

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 206,968评论 6 482
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 88,601评论 2 382
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 153,220评论 0 344
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 55,416评论 1 279
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 64,425评论 5 374
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 49,144评论 1 285
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,432评论 3 401
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 37,088评论 0 261
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 43,586评论 1 300
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,028评论 2 325
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,137评论 1 334
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,783评论 4 324
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,343评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,333评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,559评论 1 262
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 45,595评论 2 355
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,901评论 2 345

推荐阅读更多精彩内容