前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >Node.js 基础入门

Node.js 基础入门

原创
作者头像
王秀龙
修改2021-08-23 18:34:16
1.4K0
修改2021-08-23 18:34:16
举报

一、Node.js 简介

Node.js 是一个基于 Chrome V8 引擎 的 JavaScript 运行时环境

安装与运行

下载

https://nodejs.org/zh-cn/download/
下载
下载

创建项目

mkdir node
cd node
npm init -y

新建 index.js 文件

const { readFile } = require('fs')

readFile('./package.json', { encoding: 'utf-8' }, (err, data) => {
    if (err) {
        throw err;
    }
    console.log(data)
})

输入 package.json 文件

node index.js
版本管理

在同一个设备上如何快速切换Node.js 版本?

版本管理工具:

  • n: 一个npm 全局的开源包,是依赖npm 来全局安装、使用的
  • fnm: 快速简单,兼容性支持.node-version和.nvmrc文件
  • nvm: 独立的软件包,Node Version Manager
特点
特点
特点
异步 I/O

当 Node.js 执行 I/O 操作时,会在响应返回并恢复操作,而不是阻塞线程并浪费CPU 循环等待

异步 I/O
异步 I/O
单线程

Node.js 保持了 JavaScript 在浏览器中单线程的特点

优点:

  • 不用处处在意状态同步问题,不会发生死锁
  • 没有线程上下文切换带来的性能开销

缺点:

  • 无法利用多核 CPU
  • 错误会引起整个应用退出,健壮性不足
  • 大量计算占用导致CPU,无法继续执行

浏览器为例,浏览器是多进程,JS 引擎单线程

Browser 进程:浏览器主进程,只有一个

插件进程:插件使用时才创建

GPU 进程:最多一个用于3D 绘制

渲染进程:页面渲染、JS执行、事件处理

  • GUI 渲染线程+
  • JS 引擎线程+ V8
  • 事件触发线程
  • 定时器触发线程
  • 异步请求
跨平台

兼容Windows 和*nix 平台,主要得益于在操作系统与Node 上层模块系统之间构建了一层平台架构

跨平台
跨平台
应用场景

Node.js 在大部分领域都占有一席之地,尤其是I/O密集型的

  • Web 应用:Express / Koa
  • 前端构建: WebpackGUI
  • 客户端软件: VSCode / 网易云音乐
  • 其它:实时通讯、爬虫、CLI 等

二、模块化机制

  1. 何为模块化? 根据功能或业务将一个大程序拆分成互相依赖的小文件,再用简单的方式拼装起来
  2. 为什么模块化? 无模块化问题所有script 标签必须保证顺序正确,否则会依赖报错 全局变量存在命名冲突,占用内存无法被回收 IIFE/namespace 会导致代码可读性低等诸多问题
CommonJS规范

Node.js 支持 CommonJS 模块规范,采用同步机制加载模块

// greeting.js
const prefix = 'hello';
const sayHi = function () {
    return prefix + 'world';
}
module.exports = {
    sayHi
}

// index.js
const { sayHi } = require('./greeting');
sayHi();

exports = module.exports = { }

// greeting.js
const prefix = 'hello';
const sayHi = function () {
    return `${prefix}  world`;
}
exports.sayHi = sayHi;

// index.js
const { sayHi } = require('./greeting');
sayHi();

CommonJS 中 exports、require、module、__filename、__dirname 变量

function (exports, require, module, __filename, __dirname) {
    const m = 1;
    module.exports.m = m;
}

加载方式:

  1. 加载内置模块require('fs')
  2. 加载相对 | | 绝对路径的文件模块 require('/User/.../file.js') require('./file.js')
  3. 加载 npm 包 require('lodash')

npm 包查找原则:

require('lodash')

  1. 当前目录node_modules
  2. 如果没有,父级目录的node_modules
  3. 如果没有,沿着路径向上递归,直到根目录下node_modules
  4. 找到之后会加载package.json main 指向的文件,如果没有package.json 则依次查找index.js、index.json、index.node

require.cache

require.cache 中缓存着加载过的模块,缓存的原因:同步加载

  1. 文件模块查找耗时,如果每次require 都需要重新遍历查找,性能会比较差;
  2. 在实际开发中,模块可能包含副作用代码
// 有缓存
const mod1 = require('./foo');
const mod2 = require('./foo');
console.log(mod1 === mod2);     // true

//无缓存
function requireUncached(module) {
    delete require.cache[require.resolve(module)];
    return require(module);
}
const mod3 = requireUncached('./foo');
console.log(mod1 === mod3);     // false
其他模块化规范
  • AMD 是 RequireJS 在推广过程中规范化产出,异步加载,推崇依赖前置
  • CMD 是 SeaJS 在推广过程中规范化产出,异步加载,推崇就近依赖
  • UMD (Universal Module Definition) 规范,兼容 AMD 和 CommonJS 模式
  • ES Modules (ESM),语言层面的模块化规范,与环境无关,可借助 babel 编译
常用模块介绍

文件

var fs = require("fs") // 引入 fs 模块
fs.readFile(filename, [options], callback); //读取文件
fs.writeFile(filename, data, [options], callback); // 写文件
fs.appendFile(filename, data, [options], callback); //以追加的方式写文件
fs.open(filename, flags, [mode], callback); //打开文件
fs.mkdir(path, [mode], callback); //创建目录:
fs.readdir(path, callback); //读取目录
fs.exists(path, callback); //查看文件与目录是否存在

Path 模块

var path = require("path") // 引入 path 模块
path.basename(path[, ext]); //返回path的最后-部分
path.dirname(path); // 返回path的目录名
path.normalize(path);//路径解析,得到规范路径
path.isAbsolute(path); //判断路径是否是绝对路径
path.relative(form,to); //方法根据当前工作目录返回从from 到to的相对路径
path.resolve([...paths]); //将路径或路径片段的序列解析为绝对路径

OS 模块

var os = require("os") //引入 os 模块
os.cpus(); //返回每个逻辑cpu内核信息
os.hostname(); //返回操作系统的主机名
os.platform(); //返回标识操作系统平台的字符串
os.userInfo([options]); //返回关于当前有效用户的信息

三、包管理机制

npm介绍

NPM 是Node.js 中的包管理器,提供了安装、删除等其它命令来管理包

常用命令:

  • npm init
  • npm config
  • npm run cmd
  • npm install pkg
  • npm uninstall pkg
  • npm update pkg
  • npm info pkg
  • npm publish

package.json 文件

  • name 包名称
  • version 版本号
  • main 入口文件
  • scripts 执行脚本
  • dependencies 线上依赖
  • devDependencies 开发依赖
  • repository 代码托管地址

更多 package.json 配置

https://docs.npmjs.com/cli/v7/configuring-npm/package-json

依赖

  • dependencies 业务依赖,应用发布后正常执行所需要的包
  • devDependencies 开发依赖,只用于开发环境
  • peerDependencies 同等依赖,比如一个webpack 插件依赖特定版本的webpack
  • bundledDependencies 打包依赖(npm run pack),必须已经在devDep 或者dep声明过
  • optionalDependencies 可选依赖

私有 npm

其它

  • 并行安装
  • 扁平管理
  • 锁文件(lockfile)
  • 缓存优化
  • ...
  • npm7 | yarn => lock/扁平/缓存...
  • pnpm => monorepo/硬、符号链接/安全性高...

四、异步编程

Callback

目的:读取 package.json 中main 字段对应的文件内容

问题:如何解决回调地狱?

const fs = require('fs')

fs.readFile('./package.json', { encoding: 'utf-8' }, (err, data) => {
    if (err) throw err;
    const { main } = JSON.parse(data);
    fs.readFile(main, { encoding: 'utf-8' }, (err, data) => {
        if (err) throw err;
        console.log(data)
    })
})
Promise

Promise 是一个具有四个状态的有限状态机,其中三个核心状态为 Pending(挂起),Fulfilled(完成)、Rejected(拒绝),以及还有一个未开始状态。

异步
异步

使用 Promise , 实现读取 package.json 中 main 字段对应的文件内容

const { readFile } = require('fs/promises')

readFile('./package.json', { encoding: 'utf-8' }).then(res => {
    return JSON.parse(res);
}).then(data => {
    return readFile(data.main, { encoding: 'utf-8' });
}).then(res => {
    console.log(res);
})

如何将 Callback 转为 Promise 形式?ugl.promisify

function promisify(fn, receiver) {
    return (...args) => {
        return new Promise((resolve, reject) => {
            fn.apply(receiver, [...args, (err, res) => {
                return err ? reject(err) : resolve(res);
            }]);
        });
    };
}
const readFilePromise = promisify(fs.readFile, fs);
await

await 函数使用 try catch 捕获异常(注意并行处理)

const { readFile } = require('fs/promises')

async () => {
    const { main } = JSON.parse(await readFile('./package.json', { encoding: 'utf-8' }));
    const data = await readFile(main, { encoding: 'utf-8' });
    console.log(data);
}

Event

发布订阅模式,Node.js 内置events 模块

比如 HTTP server on('request') 事件监听

//发布订阅模式
const EventEmitter = require('events');

class MyEmitter extends EventEmitter { }
const myEmitter = new MyEmitter();
myEmitter.on('event', () => {
    console.log('an event occurred!');
});
myEmitter.emit('event');

// server 监听request 事件
const http = require('http');
const server = http.createServer((req, res) => {
	res.end('hello')
});
server.on('request', (req, res) => {
    console.log(req.url);
});
server.listen(3000);

五、Web 应用开发

HTTP 模块

搭建一个最简单的HTTP 服务?Node.js 内置HTTP 模块

const http = require('http');

http.createServer((req, res) => {
    res.end('hello World\n');
}).listen(3000, () => {
    console.log('App running at http://127.0.0.1:3000/')
})
Koa 介绍

Koa —— 基于 Node.js 平台的下一代Web 开发框架 Koa 它仅仅提供了一个轻量优雅的函数库,使得编写Web 应用变得得心应手, 不在内核方法中绑定任何中间件

const Koa = require('koa');
const app = new Koa();

app.use(async ctx => {
    ctx.body = 'Hello World';
});

app.listen(3000, () => {
    console.log('App running at http://127.0.0.1:3000/')
});

执行过程

  • 服务启动
    • 实例化 application
    • 注册中间件
    • 创建服务、监听端口
  • 接受/处理请求
    • 获取请求req、res 对象
    • req -> request、res -> response 封装
    • request & response -> context
    • 执行中间件
    • 输出设置到ctx.body 上的内容
Koa 中间件

Koa 应用程序是一个包含一组中间件函数的对象,它是按照洋葱模型组织和执行的

Koa
Koa

常用中间件

  • koa-router:路由解析
  • koa-body: request body 解析
  • koa-logger:日志记录
  • koa-views: 模板渲染
  • koa2-cors :跨域处理
  • koa-session:session 处理
  • koa-helmet:安全防护
  • ...

Koa 中间件繁多,质量参差不齐,需要合理选择,高效组合...

基于Koa 的前端框架

开源:ThinkJS / Egg ...

内部:Turbo、Era、Gulu ...

它们做了什么?

  • Koa 对象 response / request / context / application 等扩展
  • Koa 常用中间件库
  • 公司内部服务支持
  • 进程管理
  • 脚手架

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 一、Node.js 简介
    • 安装与运行
      • 版本管理
        • 特点
          • 异步 I/O
          • 单线程
          • 跨平台
        • 应用场景
        • 二、模块化机制
          • CommonJS规范
            • 其他模块化规范
              • 常用模块介绍
              • 三、包管理机制
                • npm介绍
                • 四、异步编程
                  • Callback
                    • Promise
                      • await
                      • 五、Web 应用开发
                        • HTTP 模块
                          • Koa 介绍
                            • Koa 中间件
                              • 基于Koa 的前端框架
                              相关产品与服务
                              消息队列 TDMQ
                              消息队列 TDMQ (Tencent Distributed Message Queue)是腾讯基于 Apache Pulsar 自研的一个云原生消息中间件系列,其中包含兼容Pulsar、RabbitMQ、RocketMQ 等协议的消息队列子产品,得益于其底层计算与存储分离的架构,TDMQ 具备良好的弹性伸缩以及故障恢复能力。
                              领券
                              问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档