【Node.js】初探node


一、Node基本概念


01. 基本概念

  • 略…

02. 基本组成

  • Node.js是由 ECMAScriptNode环境提供的一些附加API组成的,包括文件、网络、路径等一些更加强大的APl

03. 安装与使用

  • 安装

  • 使用:命令行运行js文件

    node index.js
    

二、模块化开发


01. JS文件的不足之处

  • 文件依赖

  • 命名冲突


02. 开发规范

  • Node.js规定:

    • 一个JavaScrip文件就是一个模块
    • 模块内部定义的变量和函数默认情况下在外部无法得到
  • 在模块内部:

    • 使用 exports.属性名对象进行成员导岀
    • 使用module.exports.属性名导出成员
    • 使用 require方法导入其他模块
      • require方法返回模块导出的exports对象

03. 模块化

  • 一个功能就是一个模块,多个模块可以组宬完整应用,抽离一个模块不会影响其他功能的运行

  • 语法示例:

    // first.js
    let number = 10;
    let say = arg => console.log(arg);
    // 导出成员,使用 exports
    exports.number = number;
    exports.say = say;
    // 这里的exports.number是exports的一个属性名,可以设置其他值,然后把number值赋值给了exports的这个属性 
    
    // second.js
    // 导入模块first.js,使用 require
    const first = require("./first.js");	// 注意模块路径
    // 可以调用模块first.js中的属性、方法
    first.number;		// 结果:10
    first.say("Hello");	// 结果:Hello	
    
  • exportsmodule.exports的区别

    • exportsmodule.exports的别名(地址引用关系)
    • 当重新赋值后,如果 exports对象和 moudle.exports对象指向的不是同一个对象时,以module.exports为准

三、系统模块

Node运行环境提供的API为系统模块


01. 文件模块fs

file system:文件操作系统


  • 引入模块:
const fs = require("fs");

【特别注意】
  • 文件模块fs的所有方法都是异步
  • 可以加上Sync转为同步
(1)读取文件内容
  • 语法结构

    fs.readFile("要读取的文件", ["文件编码"], callback);
    
    • callback:获取文件读取结果,错误优先回调函数
  • 语法示例

    fs.readFile("./index.js","utf8",(error,doc) =>{
        // 如果文件读取发生错误,error 的值为一个对象,内部包含错误信息
        if(error){
            res.end("文件读取失败");
            throw error;	// 在此处抛出错误
        }
        // 文件读取成功,则 error 的值为 null
        // doc 参数为文件内容
        res.end("文件读取成功!!");
    });
    
(2)写入文件内容
  • 语法结构

    fs.writeFile("要写入的文件", "要写入的数据", callback);
    
    • 写入文件:有则写入,没有则创建并写入
    • 【注意】:第二个参数是写入的内容
  • 语法示例

    fs.writeFile("./demo.txt", "即将写入的内容", (error) => {
    	if(error){
             res.end("文件写入失败");
            throw error;
        }
        res.end("文件写入成功!!");
    });
    

02. 路径模块

  • 引入模块

    const path = require("path");
    
  • 作用:进行路径拼接

    const myPath = path.join("路径1", "路径2", ...);
    
  • 绝对路径:使用 __dirname 获取当前文件所在的绝对路径


03. HTTP模块

  • 引入模块:

    const http = require("http");
    
  • 使用模块:

    http.createServer( (req,res) => {
        // req,res的处理
    });
    
    • req:获取客户端传递的信息

      • req.url:获取url

      • req.method:获取客户端提交信息的方式“GET”、“POST”

        【注意】是大写的

    • res:给浏览器的响应信息

      • res.writeHead(状态码,{...}):设置响应头

        res.write(400,{
            "content-type": "text/html;charset=utf8"
        });
        
        // 200 是状态码
        // "content-type"是文件编码类型
        
      • res.write():在页面输出内容

      • res.end():结束响应

        必须的,只能有一个

        因为结束响应后,便不再响应消息了

        res.end("响应结束");
        // 可在里面添加字符串
        // 等价于
        res.write("响应结束");
        res.end();
        

04. URL模块

  • 引入模块

    const url = require("url");
    
  • 作用:解析客户端提交的URL信息

    url.parse(myUrl);
    
    • 使用 url.parse() ,可以解析URL信息为对象
    url.parse(myUrl,true).query;
    
    • 添加第二个参数 true ,可以将URL对象里的 query 属性中的数据从【字符串】转换为【对象】
    url.parse(req.url).pathname;
    
    • 请求路径,不包含参数,端口号后面的路径

四、第三方模块


01. 获取方法

(1)基本概念

  • 具有特定玏能的、能直接使用的模块即第三方模块,又称为
  • 两种形式
    • js文件形式,提供实现项目具体功能的API接口
    • 命令行工具形式,辅助项目开发

(2)下载安装

  • npm(node package manager):node的第三方模块管理工具

  • 下载

    npm install 模块名称
    

    默认下载到当前工作目录

  • 删除

    npm uninstall 模块名称
    

02. 关于nrm

  • 作用:用于切换npm下载地址

  • 使用:

    npm install nrm -g
    
    • 下载并安装,-g是全局安装
    nrm ls
    
    • 查询可用下载地址列表
    nem use 查询到的下载地址
    
    • 切换要下载的地址

03. 关于nodemon

  • 作用:可以在文件修改后,自动执行文件

  • 使用:

    • nodemon命令替代node
    • 使用Ctrl+c终止操作
    nodemon app.js
    

04. 关于gulp

(详情看后文~~~)


五、package.json


01. node.js产生的问题

  • 使用node,会产生许多文件夹,过于零碎
  • 模块之间的依赖关系

02. 关于package.json文件

  • 项目描述文件,记录了当前项目信息

    • 例如项目名称、版本、当前项目依赖了哪些第三方模块等
  • 使用 npm init命令生成

  • 语法结构:

    {
      "name": "test-project",
      "version": "1.0.0",
      "description": "A Vue.js project",
      "main": "src/main.js",
      "private": true,
      "scripts": {
        "test": "npm run unit"
      },
      "keywords": [],
      "author": "",
      "license": "ISC",
      "dependencies": {
        "vue": "^2.5.2"
      }, 
      "devDependencies": {
        "autoprefixer": "^7.1.2",
        "babel-core": "^6.22.1",
      }
    }
    
  • 语法释义:

    • name 设置项目的名称
    • version 表明了项目的版本
    • description 是项目的简短描述
    • main 设置了项目的主入口点
    • private 如果设置为 true,则可以防止应用程序/软件包被意外地发布到 npm
    • scripts 定义了一组可以运行的 node 脚本命令别名
    • keywords:关键字,用关键字描述项目
    • author:项目作者
    • license:项目协议
    • dependencies 设置项目所依赖的第三方模块
    • devDependencies 设置了作为开发依赖安装的 npm 软件包的列表

03. 项目依赖与开发依赖

  • 项目依赖:dependencies

    其他人使用时,输入npm install --production,会自动到项目根目录下找package.json,在文件中找到dependencies,然后安装下面对应的第三方模块

  • 开发依赖:devDependencies

    在项目的开发阶段需要依赖,线上运营阶段不需要依赖的第三方包,称为开发依赖

    使用 npm install--save-dev命令,将添加到package.json文件的 devDependencies字段中


04. 关于package-lock.json文件

  • 作用:

    • 锁定包的版本,确保再次下载时不会因为包版本不同而产生问题
    • 加快下载速度,因为该文件中已经记录了项目所依赖第三方包的树状结构和包的下载地址,重新安装时只需下载即可

六、模块加载机制


01. 在node.js中是如何查找(加载)模块的?

(1)当模块【拥有路径】但【没有后缀】时
  • require方法根据模块路径査找模块,如果是完整路径,直接引入模块
  • 如果模块后缀省略,先找同名JS文件,没有再找同名JS文件夹
  • 如果找到了同名文件夹,找文件夹中的 index.js
  • 如果文件夹中没有index.js就会去当前文件夹中的**package.json文件中查找main选项中的入口文件**
  • 如果找指定的入口文件不存在,或者没有指定入口文件就会报错,模块没有被找到
(2)当模块【没有路径】且【没有后缀】时
  • Node.js假设它是系统模块
  • Node.js会去 node modules文件夹中
  • 首先看是否有该名字的JS文件
  • 没有,则再看是否有该名字的文件夹
  • 如果是文件夹,看里面是否有 index.js
  • 如果没有index.js,查看该文件夹中的package.json中main选项,确定模块入口文件
  • 否则找不到报错

七、第三方模块Gulp

01. gulp的基本概念

  • 基于node平台开发的前端构建工具
    • 将机械化操作编写成任务
    • 想要执行机械化操作时执行命令行任务就能自动执行了
  • 作用:
    • HTML+CSS+JS文件压缩合并
    • 语法转换
    • 公共文件抽离
    • 修改文件后,浏览器自动刷新

02. gulp的使用方法

(1)下载
npm install gulp
(2)创建
  • 在项目根目录下建立 gulpfile.js文件
  • 重构项目的文件夹结构
    • src目录:源代码文件
    • dist目录:构建后文件
(3)方法
  • gulpfile.js文件中编写任务
  • 在命令行工具中执行gulp任务
(4)使用
  • 基本方法

    • gulp.task():建立gulp任务
    • gulp.src():获取任务要处理的文件
    • gulp.dest():输出文件
    • gulp.watch():监控文件的变化
  • 语法示例

    // 引入 gulp模块
    const gulp = require("gulp");
    
    // 建立任务,两个参数:任务名+回调函数
    // gulp.task("任务名",callback)
    
    gulp.task("first", () => {
        //获取处理文件
        gulp.src(".src/css/style.css");
    	//将处理的文件输出,必须把要处理的代码写在.pipe里
        .pipe(gulp.dest("./dist/css"));
    })
    
    • 执行任务
    gulp first
    

03. gulp的插件

  • 常用插件

    • gulp-htmlminhtml文件压缩

    • gulp-csso:压缩CSS

    • gulp-babelJavaScript语法转化

    • gulp-lessless语法转化

    • gulp-uglify:压缩混淆JavaScript

    • gup-file-include公共文件包含

      • 将公共部分提取出来单独作为一个html文件

      • 在要使用这个公共部分的html文件里引回来

        // @@include("文件");
        
        @@include("./common/header.html");
        
    • browsersync:浏览器实时同步

  • 使用方法

    // npm install ~
    
    // 压缩html文件
    const htmlmin = require("gulp-htmlmin");
    
    // 创建任务
    gulp.task("gulp_html",function(){
        // 获取处理文件
        gulp.src("./index.html");
        // 压缩文件
        .pipe(htmlmin({collpaseWhitespace: true}));	//这一句是压缩空格、换行
        // 输出文件
        .pipe(gulp.dest("./dist"));
    });
    
    // 压缩CSS、less
    const csso = require("gulp.csso");
    const less = require("gulp.less");
    //创建任务
    gulp.task("gulp_css",() =>{
        // 获取处理文件
        gulp.src(["./src/css/*.less","./src/css/*.css"]); // 数组形式,获取多个,*.css选择所有CSS文件
        // 转换less语法
        .pipe(less());
        // 压缩CSS文件
        .pipe(css0());
        // 输出文件
        .pipe(gulp.dest("./dist/css"));
    });
    
    // js任务
    const uglify = require("gulp.uglify");	// 压缩
    const babel = require("gulp.babel");	//转换ES6
    // 创建任务
    gulp.task("gulp_js",() =>{
        // 获取
        gulp.src("./src/js/*.js");
        // 转换语法
        .pipe(babel({
            // 判断当前代码运行环境,将代码转换为当前运行环境所支持的代码
            presets: ["@babel/env"]
        }))
        // 压缩JS文件
        .pipe(uglify());
        // 输出
        .pipe(gulp.dest("./dist/js"));
    });
    
    // 构建任务,一次执行多个任务
    // 创建任务:default
    gulp.task("default",["gulp_html", "gulp_css", "gulp_js"]);
    
    // 使用:gulp default   
    // 或者  gulp  (会直接执行任务名为default的任务)
    

八、搭建HTTP服务器

01. 服务器基本概念

02. 如何创建服务器

  • 语法示例

    // 引用http模块
    const http = require("http");
    // 创建web服务器
    const app = http.createServer();
    
    // 当客户端发送请求的时候
    // 用 on 监听请求事件 request
    app.on("request", (req, res) => {		
    	res.end("<h1>服务器创建成功!</h1>");
    });
    
    // 监听3000端口
    app.listen(3000);
    
    console.log("服务器已启动,监听3000端口,请访问--localhost:3000");
    

九、HTTP请求与响应处理

01. 关于HTTP协议

  • 超文本传输协议(英文:Hyper Text Transfer Protocol,缩写:HTTP)
    • 规定了如何从网站服务器传输超文本到本地浏览器
    • 它基于客户端服务器架构工作,是客户端(用户)和服务器端(网站)请求和响应的标准

02. 关于报文

在HTTP请求和响应的过程中传递的数据块就叫报文,包括要传送的数据和一些附加信息,并且要遵守规定好的格式

(1)请求报文
  • 请求方式:GET、POST

    req.method:获取客户端发送请求的方式

    req.headers:获取请求报文

    req.url:获取请求地址

(2)响应报文
  • 语法结构

    res.writeHead(http状态码,{
    	"content-type": "内容类型"
    });
    
    • HTTP状态码:

      200:请求成功

      404:请求的资源没有被找到

      500:服务器端错误

      400:客户端请求有语法错误

    • 内容类型

      text/html

      text/css

      application/javascript

      image/jpeg

      application/json


04. 关于请求参数

客户端向服务器发送请求时,有时需要携带一些客户信息,客户信息需要通过请求参数的形式传递到服务器端

(1)GET请求参数
  • 参数被放置在浏览器地址栏中的 ? 后面,每个参数一 & 符号分隔

    • 以键值对的形式存在
  • 使用url系统模块方法获得:

    const url = require("url");
    // 要解析的url地址:req.url
    // 将查询参数解析成对象形式
    url.parse(req.url,true).query;
    
(2)POST请求参数
  • 参数被放置在请求体中进行传输

  • 获取POST参数需要使用data事件和end事件

    req.on()监听事件是异步

  • 使用querystring系统模块将参数转换为对象格式

    // 导入系统模块querystring,用于将HTTP参数转换为对象格式
    const querystring = require("querystring");
    
    app.on("request",(req,res)=>{
        // post参数是通过事件的方式接受的
        // data 当请求参数传递的时候
        // end  当参数传递完成的时候
        
        let postParams = "";
        // 监听参数开始传输事件:data
        req.on("data",params => {
            postParams += params;
        });
        // 监听参数传输完毕事件:end
        req.on("end",() =>{
            console.log(querystring.parse(postParams));
        });
        
        res.end("post请求完成");
    })
    

05. 路由的概念

  • 路由是指客户端请求地址与服务器端程序代码对应关系

    简单的说,就是请求什么就响应什么

  • 使用方法

    1. 引入系统模块http

    2. 创建网站服务器

    3. 为网站服务器对象添加请求事件

    4. 实现路由功能

      • 获取客户端请求方式

      • 获取客户端请求地址

    const http = require("http");
    const url = require("url");
    
    const app = http.createServer();
    
    app.on("request",(req.res)=>{
        // 获取请求方式
        const method = req.method;
        // 获取请求地址
        const pathname = url.parse(req.url).pathname;
        
        if(method == "get"){
            if(pathname == "/" || pathname =="/index"){
                res.end();
            }else if(pathname == "/list"){
                res.end();
            }else{
                res.end();
            }
        }else if(method == "post"){
            // ...
        }
    });
    
    app.listen(3000);
    
    

06. 静态资源的访问

  • 服务器端不需要处理,可以直接响应给客户端的资源就是静态资源

    例如CSS、JavaScript. image,html文件

    动态资源:相同的请求地址,不同的传递参数,会有不同的响应资源,这种资源就是动态资源

  • 访问方法

    用当前文件的绝对路径+文件夹的路径+请求资源的url

    目的是:让用户不需要输入文件夹路径,直接输入html页面名称即可访问到

  • 语法示例

    // 首先获取当前页面url
    let pathname = url.parse(req.url).pathname;
    
    // 如果页面为 "/",则让它默认显示为 "index.html"页面
    pathname = pathname == "/" ? "/index.html" : pathname;
    
    // 再用当前文件的绝对路径+文件夹的路径+请求资源的url路径,即为要访问的页面的绝对路径
    let staticPath = path.join(__dirname,"public" + pathname);
    
    res.write("当前页面地址是:" + staticPath); //在页面写入静态资源的地址
    

十、Nodejs异步编程


01. 同步API和异步API

  • 同步API:只有当前API执行完成后,才能继续执行下一个API

    • 返回值中拿到执行的结果
  • 异步API:当前API的执行不会阻塞后续代码的执行

    • 回调函数中拿到执行结果

    • 容易出现回调地狱


02. 第一种方法——Promise

  • 目的:解决 Node.js异步编程中回调地狱的问题

  • 语法结构:

    实际上是一个构造函数,所以需要 new


    把异步函数写在Promise内部的回调函数中

    let promise = new Promise((resolve,reject)=>{
        if(true){
            // 传出成功结果
            resolve(result);
        }else{
            // 传出失败信息
        	reject(error);  
        }
        
    });
    
    • 两个参数

      • resolve:一个函数,当异步API有执行结果时,传出这个结果
      • reject:一个函数,当异步API执行失败时,传出失败信息
    • 结果处理(Promise提供链式编程)

      • 结果是包含在 Promise 对象里面的,通过then()catch()获取对象里面的内容
      promise.then( (data) => {
          console.log(data);
      }).catch( (error) => {
          console.log(error);
      });
      
  • 让异步函数顺序执行的方法

    首先,将各个异步函数分别放入Promise回调函数

    然后,把Promise实例放入函数中,作为返回值返回

    最后,使用Promise的结果处理方式依次处理

    function p1(){
      	// 返回Promise实例  
        return new Promise(...);
    }
    function p2(){
        return new Promise(...);
    }
    // 处理结果
    p1().then((result) => {
        console.log(result);
        // 这里为了满足链式编程的需求,需要返回下一个执行的函数
        return p2();
    }).then((result) => {
        console.log(result);
    })
    

03. 第二种方法——async

  • 使用async,使同步函数变为异步函数

    • 语法结构:

      • 在普通函数定义的前面加上 async 关键字
      const fun = async() =>{
          // 函数体
      };
      // 或者
      async function fun(){
          // 函数体
      }
      
      • 默认返回值就是 Promise 对象(省去了Promise对象的创建

        • 如果手动替换了 return 返回值,返回值也会被包含在 Promise 对象中

        • 如果发生错误,则需要 throw 来抛出异常

          throw 后面的内容不会执行了

          async function fun(){
          	throw "发生错误了";
          }
          
  • 使用 await 使异步函数变成同步函数

    • 只能出现在异步函数中

    • 后面只能写 Promise对象

    • 作用:暂停异步函数向下执行,直到 Promise 返回结果

      await promise;
      // 等价于 promise.then();
      
  • 语法示例:

    //  promisify 可以改造现有的异步API,让其返回值是 Promise对象,从而支持异步语法
    const promisify = require("util").pomisify;
    
    // 用 promisify 处理[异步函数],得到[新的异步函数],这个新的异步函数的返回值就是Promise对象
    const readFile = promisify(fs.readFile);
    
    // 统一执行异步函数
    async function run(){
        // await 写在异步函数内,后面跟Promise对象,返回Promise对象内部的信息
    	let p1 = await readFile();
        let p2 = await readFile();
    }
    run();
    

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值