Nodejs入门 一

620 阅读4分钟

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 是一个函数
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...
  });