Nodejs 介绍?
- 官网: Nodejs
- 提供一个让 js 可以运行在服务端的一个运行时
- Node 的底层是采用 c++ 编写
- node 他又基于 js V8内核,形成了系统级的 api 文件操作,网络编程 实现自己的 web 服务
- node 是 commonjs 规范的实现
Node 特点
- 事件驱动:node 的 api 是基于事件的 异步的
- Node 采用的是单线程(js语言的限制),只有一个主线程,但 node 可以开启多个进程
- node 适用于处理 i/o 密集型(文件读写)
- 不适合 cpu 密集型,需要大量计算的业务场景
应用场景
- 前后端分离,整合后端接口,做中间层
- 写一些工具库 webpack, cli
Node中的模块加载
模块化的好处
- 1.可以帮我们解决命名冲突的问题 (每个文件外面都会包装一个函数)
- 2.高内聚低耦合
nodejs 模块加载的原理
- 在文件执行的过程中默认 这个文件会被加一层函数
- 通过函数的参数进行传入我们在文件中可以直接访问
通过读取文件内容 将内容包装到一个自执行函数中,默认返回module.exports做为函数的结果
let a = `function (exports, require, module, __filename, __dirname) {
let a = 1
module.exports = 'hello';
return module.exports;
}(exports, require, module, xxxx, xxx)`
node 中的模块可以分为三类
- 1.核心模块/内置模块 fs http path 不需要安装 引入的时候不需要增加相对路径、绝对路径
- 2.第三方模块 require('co') 需要安装,别人写的
- 3.自定义模块 需要通过绝对路径或者相对路径进行引入
- 4.第三方模块,要先安装,查找顺序 本级目录 -> 上级目录 。。。->到根目录
const fs = require("fs");
const path = require("path");
const a = require("a");
console.log(a);
//node中默认不支持es6模块 可以用babel-node来支持
// require 区别于 import 是动态的
if (true) {
const fs = require("fs");
}
模块的循环引用
Node 核心模块
global、process
// 1.global上属性是全局的,不需要引入
console.log(Object.keys(global));
global.a = 1000;
console.log(a);
console.log(__dirname);
console.log(__filename);
// 2、----process------
console.log(Object.keys(process));
// node版本
console.log(process.version);
// 平台 win32 darwin
console.log(process.platform);
// set export
console.log(process.env);
console.log(process.env.NODE_ENV);
// // 参数
-- 作为key
console.log(process.argv);
console.log(process.pid);
console.log(process.cwd());
Promise.resolve().then(() => {
console.log("Promise");
});
process.nextTick(() => {
console.log("nextTick");
});
fs-文件读写
const fs = require("fs");
const path = require("path");
// fs fileSystem 文件系统 可以帮我们操作文件 目录....
// path.resolve path.join
const absPath = path.resolve(__dirname, "note.md");
// 同步Api
const data = fs.readFileSync(absPath);
console.log(data.toString());
// node api 约定 error first
fs.readFile(absPath, (err, data) => {
if (err) {
console.log(err);
return;
}
console.log(data.toString());
});
const newFile = path.resolve(__dirname, "test.txt");
// flag a-追加 w-默认写入
fs.writeFile(newFile, "hello world", { flag: "w" }, (err, data) => {
if (!err) {
console.log("写入成功");
}
});
// fs.appendFile 等价于上面
http-网络服务
- server.js
const http = require("http");
// js 是单线程 node 也是单线程的
let server = http.createServer((req, res) => {
res.end(`{"code": 0}`);
});
//端口号来监听请求
server.listen(3100, () => {
console.log("server start");
});
- client.js
const http = require("http");
http.get("http://localhost:3100", res => {
let rawData = "";
res.on("data", chunk => {
rawData += chunk;
});
res.on("end", () => {
try {
const parsedData = JSON.parse(rawData);
console.log("parsedData", parsedData);
} catch (e) {
console.error(e.message);
}
});
});
events-事件处理
let EventEmitter = require("events");
class MyEvent extends EventEmitter {}
const e = new MyEvent();
e.on("add", num => {
console.log("add", num);
});
e.emit("add", 12, 12, 122);
e.emit("add", 1);
e.once("min", () => {
console.log("once");
});
e.emit("min");
e.emit("min");
e.emit("min");
buffer-数据流
// Buffer 创建后不可更改
const b1 = Buffer.from("hello");
console.log(b1);
// 中文 1=3字节
const b2 = Buffer.from("你好", "utf8");
console.log(b2);
console.log(b2.toString());
console.log(b2.toString("hex"));
// base64 编码 会比原来大1/3
console.log(b2.toString("base64"));
const b3 = Buffer.alloc(10);
console.log(b3.toString("hex"));
// // 拼接
const b4 = Buffer.concat([b1, b2]);
console.log(b4.toString());
path-路径处理
const path = require("path");
// 如果需要拼接/ 必须采用join resolve会回到根目录下
let r = path.join(__dirname, "a", "b", "c", "/");
// 拼接 join 可以拼接/
// let r1 = path.resolve(__dirname, "a", "b", "c", "/"); // 解析出绝对路径
// 获取扩展名
let ext = path.extname("a.min.js");
// 判断后缀
let basename = path.basename("a.min.js", ".js");
// console.log(ext, basename);
console.log(basename);
代码传送
基于 Node 核心模块实现一个静态文件 web 服务
const http = require("http");
const path = require("path");
const url = require("url");
const fs = require("fs");
const mime = require("mime");
function notFound(res) {
res.statusCode = 404;
res.end("Not Found");
}
let server = http.createServer((req, res) => {
let { pathname, query } = url.parse(req.url, true);
const absPath = path.join(__dirname, pathname);
// 我要先检测这个路径是不是目录 如果是目录默认查找index.html ,如果是文件直接返回
fs.stat(absPath, function (err, statObj) {
if (err) return notFound(res);
if (statObj.isFile()) {
fs.readFile(absPath, function (err, data) {
if (err) return notFound(res);
res.setHeader("Content-Type", mime.getType(absPath) + ";charset=utf-8");
res.end(data);
});
} else {
// 先看是否有index.html 如果有我就返回
fs.readFile(path.join(absPath, "index.html"), function (err, data) {
if (err) return notFound(res);
res.setHeader("Content-Type", "text/html;charset=utf-8");
res.end(data);
});
}
});
});
server.listen(3000);
express 框架介绍
- 官网:Express
express 简单使用
// express 是一个函数
let express = require("./express");
// 通过express执行产生一个应用
let app = express();
// 当请求到来时 路径和方法一致会触发对应的函数
// req,res 都是原生的node中的req和res
app.get("/hello", function (req, res) {
res.end("hello");
});
app.listen(3000);
express 静态文件服务
app.use(express.static("public"));
app.route(path)
app
.route("/events")
.all(function (req, res, next) {
// runs for all HTTP verbs first
// think of it as route specific middleware!
})
.get(function (req, res, next) {
res.json({});
})
.post(function (req, res, next) {
// maybe add a new event...
});