nodejs 入门基本操作

nodejs,入门,基本操作 · 浏览次数 : 288

小编点评

**代码解析** 这段代码展示了如何使用 Node.js 的 `fs` 模块读取和写入文件,并使用 `express` 模块创建一个 HTTP 服务。 **1. 文件操作** * `path.resolve(__dirname, dir)` 获取当前文件所在的目录。 * `fs.writeFileSync()` 在指定文件路径中写入数据。 * `fs.readFileSync()` 读取指定文件路径的内容。 **2. HTTP 服务** * `express` 创建了一个名为 `app` 的实例。 * `app.get('/', ...)` 处理所有 HTTP GET 请求到 `/` 路由。 * `app.listen(port, ...)` 启动服务,监听端口 `port`。 **3. 中间件** * 使用 `use()` 函数注册中间件。 * 中间件可以执行任何需要进行验证或处理的操作。 * 例如,可以使用中间件验证用户身份。 **4. 洋葱模型** * `InterInterceptor` 类使用了一个数组来存储中间件。 * 在 `run()` 方法中,从右往左遍历中间件并执行它们。 * 使用 `reduceRight()` 函数将中间件串联起来。 **5. 示例代码** 该代码展示了如何使用 `fs` 和 `express` 模块实现文件操作和 HTTP 服务,以及如何使用中间件和洋葱模型进行扩展。 **其他相关知识** * Node.js 中的文件操作使用异步 API,这确保了并发操作的效率。 * `express` 是一个流行的 Node.js 框架,它提供了一个完整的 API,包括中间件、路由和数据库等功能。 * 中间件可以执行任何需要进行验证或处理的操作,例如身份验证、 session 验证和表单验证。 * 洋葱模型是一种设计模式,它通过将多个中间件串联起来,实现了一个更复杂的流程。

正文

操作fs模块

const path = require("path");
const fs = require("fs");

/*
相对路径是命令窗口执行的目录
node 提供了path模块来操作路径相关的api, 其中__dirname是一个内置的变量,返回当前文件所在的目录
*/
const getDirUrl = dir => {
  return path.resolve(__dirname, dir);
};
for (let i = 0; i < 5; i++) {
  fs.writeFileSync(getDirUrl("./create01.text"), i + "、我是测试数据" + i + "\n", {
    flag: "a+",
    encoding: "utf-8"
  });
}

console.log("hello nodejs");

const data = fs.readFileSync(getDirUrl("./create01.text"), {encoding: 'utf-8'}).toString()
console.log('同步读取')
console.log(data)

console.log('异步读取')
fs.readFile(getDirUrl("./create01.text"), (err, data) => {
  if(!err) {
    console.log(data.toString());
  } else {
    console.error(err);
  }
});

在窗口执行对应的目录即可,我这里是:

操作http模块

// 1. 导入http模块
const http = require("http");
const fs = require("fs");
const path = require("path");

const mimes = {
  html: "text/html",
  css: "text/css",
  js: "text/javascript",
  png: "image/png",
  jpg: "image/jpeg",
  gif: "image/gif",
  mp4: "video/mp4",
  mp3: "audio/mpeg",
  json: "application/json"
};
//2. 创建服务对象 create 创建 server 服务
// request 意为请求. 是对请求报文的封装对象, 通过 request 对象可以获得请求报文的数据
// response 意为响应. 是对响应报文的封装对象, 通过 response 对象可以设置响应报文
const server = http.createServer((req, res) => {
  let { url, method } = req; 
  // 文件夹路径
  const rootDir = __dirname + "/public";
    
  let filePath = rootDir + url;
  if (!fs.existsSync(filePath)) {
    return
  }
  // 读取内容
  fs.readFile(filePath, (err, data) => {
    if (err) {
      console.log(err);
      //设置字符集
      res.setHeader('content-type','text/html;charset=utf-8');
      //判断错误的代号
      switch(err.code){
        case 'ENOENT':
          res.statusCode = 404;
          res.end('<h1>404 Not Found</h1>');
        case 'EPERM':
          res.statusCode = 403;
          res.end('<h1>403 Forbidden</h1>');
        default:
          res.statusCode = 500;
          res.end('<h1>500 Internal Server Error</h1>');
      }
      return;
    }
    //获取文件的后缀名
    let ext = path.extname(filePath).slice(1);
    //获取对应的类型
    let type = mimes[ext];
    if(type){
      if(ext === 'html'){
        res.setHeader('content-type', type + ';charset=utf-8');
      }else{
        res.setHeader('content-type', type);
      }
    }else{
      //没有匹配到-默认设置二进制文件类型
      res.setHeader('content-type', 'application/octet-stream');
    }
    //响应文件内容
    res.end(data);
  });
});

//3. 监听端口, 启动服务
server.listen(9000, () => {
  console.log("服务已经启动,9000端口监听中...");
});

如上最简单的http 服务起来了,在浏览器中 输入 http://localhost:9000/index.html 得到如下页面

通过匹配后缀,在public文件中返回对应的资源,代码结构如下

都是一些很简单的代码就不贴了,如果需要留下邮箱即可。

其他模块看看官网的文档即可,不在记录。

框架

上面都是通过原始的方式来使用node,其实node的生态也很丰富,有很多的框架让我们选择,如 express、koa2、nestjs、midwayjs 等等

express 基本使用

// 1.0 导入express
const express = require('express')
// 2.0 express 实例
const app = express()
const port = 9000

// 3.0 路由
app.get('/', (req, res) => {
  res.send('基本使用 Hello World!')
})

// 启动服务
app.listen(port, () => {
  console.log(`启动服务,端口: ${port}`)
})

通常我们使用脚手架,这样可以得到统一的项目结构 如 express_ generator,具体查看express 官网

中间件-洋葱模型

  目前比较流行的 nodejs http 服务框架使用拦截器模式,这种模式将 http 请求响应的过程分为若干切面,每个切面上进行一项或若干项关联的操作。比如说,我们可以通过不同的拦截切面处理用户信息验证、会话(session)验证、表单数据验证、query 解析,或者业务逻辑处理等等。这种架构设计让切面与切面之间彼此独立。

有点面向切面编程的概念,不知道对不对。

手动实现一个拦截器:实现类似如下效果

async (ctx, next) => {
  do sth...
}

通过调用next 执行下一个函数,可以中途return退出,也可以继续调用next直到最后一个函数,然后在一层一层的返回,洋葱的结构跟这个类似,所以叫洋葱模型。

这里的中间件其实是一个函数,在外层使用use 注入进来。

执行第一个中间件的fn,调用next 进入到下一个中间件,继续执行下一个fn,调用next 友进入下一个中间件,继续重复上述逻辑,直至最后一个中间件,直至最后一个中间件,就会执行 next 语句后面的代码,然后继续上一个中间件的next后置语句,继续重复上述逻辑,直至执行第一个中间件的next后置语句,最后输出,这个执行的机制,称为洋葱模型
 

模拟洋葱模型

 洋葱模型关键在于怎么处理next 参数,next是下一个函数的引用, ,可以通过我们索引加闭包,或者累加器的形式来处理,为了方便直接使用累加器的形式即可,如下代码:

/*
  这个思路通过利用累加器函数的特性,返回一个函数
*/
class Interceptor {
  aspects = [];
  use (fn) {
    this.aspects.push(fn)
    return this
  }
  async run (context) {
    // 从右往左开始遍历
    const proc = this.aspects.reduceRight(
      function (a, b) {
        let flag = false
        return async () => {
          // a 上一个fn,也就是调用的时传入的 next
          if (flag) {
            return
          }
          flag = true
          await b(context, a)
        }
    },() => Promise.resolve())
    try {
      // 通过这个reduceRight 让函数串起来了
      await proc()
    } catch (e) {
      console.error(e);
    }
  }
}

// 测试
const inter = new Interceptor()
inter.use(function a(context, next) {
  console.log("a");
  next();
  console.log("a_after");
});
inter.use(function b(context, next) {
  console.log("b");
  next();
  console.log("b_after");
});
inter.use(function c(context, next) {
  console.log("c");
  next();
  console.log("c_after");
});
inter.use(function d(context, next) {
  console.log("d");
  next();
  console.log("d_after");
});
inter.run();

输出a、b、c、d、d_after、c_after、b_after、a_after 其中koa2 源码中使用了索引加闭包的形式来处理 源码

小结

  理解了nodejs 写起来还是挺顺手的,官网文档也还好。至于其他如sql路由保持会话状态等后台基本知识点,看看相关文档即可,并没有什么难度。

  nodejs 入门基本也结束了。

与nodejs 入门基本操作相似的内容:

nodejs 入门基本操作

操作fs模块 const path = require("path"); const fs = require("fs"); /* 相对路径是命令窗口执行的目录 node 提供了path模块来操作路径相关的api, 其中__dirname是一个内置的变量,返回当前文件所在的目录 */ const g

nodejs 入门基本概念

nodejs 的诞生 Node.js 是2009的时候由大神 Ryan Dahl 开发的。Ryan 的本职工作是用 C++ 写服务器,后来他总结出一个经验,一个高性能服务器应该是满足“事件驱动,非阻塞 I/O”模型的。C++ 开发起来比较麻烦,于是 Ryan 就想找一种更高级的语言,以便快速开发。

学node 之前你要知道这些

初识nodejs 19年年底一个偶然的机会接到年会任务,有微信扫码登录、投票、弹幕等功能,于是决定用node 来写几个服务,结果也比较顺利。 当时用看了下koa2的官方文档,知道怎么连接数据库、怎么映射表实体,怎么处理http,怎么处理异常等,就可以直接写起来了。从应用层面上来说 nodejs 入门

nestjs入门学习总结(三):集成typeorm并实现一个curd操作

### typeorm熟悉 TypeORM 是一个ORM框架,它可以运行在 NodeJS、Browser、Cordova、PhoneGap、Ionic、React Native、Expo 和 Electron 平台上,可以与 TypeScript 和 JavaScript (ES5,ES6,ES7,

安装nodejs易遇到的坑

@目录背景描述流程步骤小结 背景描述 我的服务器是centos7.9,打算先直接通过yum安装,但是yum不能指定node版本,我直接指定显示404找不到,然后我设置了下node下载的源,还是不行。那我走手动下载安装的方式吧 流程步骤 首先根据这篇文章要安装前置扩展 yum install cent

NODEJS通过发送json数据查询目标服务,实现服务器状态监控,发现异常发送到微信群提醒

root@aea87fa6e6a2:/home/node# cat login2.js const request = require('request-promise'); const moment = require('moment'); const cron = require('node-c

NodeJS 实战系列:如何设计 try catch

本文将通过一个 NodeJS 程序里无效的错误捕获示例,来讲解错误捕获里常见的陷阱。错误捕获不是凭感觉添加 try catch 语句,它的首要目的是提供有效的错误排查信息,只有精心设计的错误捕获才有可能完成这个使命。针对哪些方面去精心设计就是本篇文章里想讨论的内容

NodeJS 实战系列:DevOps 尚未解决的问题

本文将通过展示 NodeJS 应用里环境变量的提取过程,来一窥 DevOps 技术是如何应用在现在云平台上的运维工作中的。同时我也想让大家在这里看到 DevOps 的另外一面,即它并非全能,从本地开发到持续部署再到实际运行,有一些运维鸿沟依然还未被填平。“人工操作”依然是工作中的最大风险。

NodeJS 实战系列:模块设计与文件分类

我们从一个最简单的需求开始,来探索我们应该从哪些方面思考模块设计,以及如何将不同的文件分类。之所以说“思考”,是因为我在这篇文章里更多的是提供一类解决问题的范式,而非统一的标准答案,能够为你提供一丁点的启发就好

NodeJS 实战系列:个人开发者应该如何选购云服务

这文章至少值一千元,因为这是我保守估计花出去的冤枉钱(请自行脑补一个苦笑的 emoji) 文章中会穿插选择云服务的一些建议,当然也会提供一些“薅羊毛”的技巧。不过在此之前我们要想清楚一件更重要的事情:我为了什么购买云服务 做产品还是做技术 这个问题不仅决定了你接下来的购买策略,还是你编码开始的前提。