zoukankan      html  css  js  c++  java
  • Nodejs笔记

    nodejs基础知识

    nodejs和js的异同

    相同点 javascript和nodejs
    以ECMAScript为基础 数据结构的定义,语法、内置对象和方法等都相同。

    不同点 javascript nodejs
    顶层对象 window global
    操作对象 操作浏览器,属前端范畴。包括↓
    DOM: 操作页面元素的方法;
    BOM: 操作浏览器元素的方法。
    操作系统/网络等,更偏向于后端。包括↓
    OS: 操作操作系统的方法;
    file: 操作文件系统的方法;
    net: 操作网页的方法;
    database: 操作数据库的方法;
    net: 操作网页的方法。
    模块概念

    nodejs的使用

    nodejs软件是无界面形式的,打开后类似于命令行,且可以直接在命令行里打开nodejs文件。

    操作命令行

    • windows下,通过win+r可以直接打开运行,输入cmd,打开命令行界面
    • 直接敲 node +回车,若得到 >和闪动的光标,表示node安装正确
    • 按2次 ctrl+c可结束执行进程
    • win7在命令行里输入CLS可清屏
    • 命令行里输入node+空格+要运行的程序
    • 命令行内不区分大小写
    • cd回到根目录,cd..回到上级目录
    • 后面输入路径, >后面输入命令

    nodejs中的模块

    • 在node中,文件和模块是一一对应的,一个文件就是一个模块
    • 每个模块都有自己的作用域
    • 通过var申明的并不是全局变量,而是该模块作用域下的变量
    • node中要通过 global.变量名 的方式申明全局变量,前面不用加var
    • node中,像全局变量,实际上是当前模块下的变量有:

    __filename → 当前文件被解析后的绝对路径,是属性,末尾无括号

    模块加载机制

    在js中通过<script>标签引入其他js文件,但在node中没有标签的概念,它是用模块加载机制来引入其他文件。即:
    require方法 → require('模块地址'); → 使用时要注意两个问题:

    • 一是路径问题:

      1. 地址之间用/,而不是
      2. 既可以写绝对地址,也可以写相对地址
      3. 写相对地址时,若是同一文件夹下的文件,不能省略./
      4. 一旦直接写文件名,会加载node中的核心模块,也就是node_modules中的模块

    • 二是文件查找问题:

    查找顺序:文件名→文件名.js→文件名.json→文件名.node→还找不到,报错

    module和exports

    在node中用var定义的变量是当前模块下的变量,无法直接和外部模块共享,解决办法:

    1. global将变量定义为全局变量;→不推荐这样做
    2. 利用每个模块内置的module对象;
    3. 利用每个模块内置的exports对象;

    module对象

    module对象保存和提供了与当前模块有关的一些信息,比如,id是当前模块的唯一标识;filename是当前模块的文件名称;children是当前模块加载的其他模块的信息。
    module对象中有一个子对象,即exports属性,可以将当前模块中的变量暴露出去;使用方法:module.exports.属性名=变量名;例:

    var a=20;
    module.exports.a=a;
    

    require方法返回的就是被调用模块的module.exports属性;

    exports对象

    每个模块中内置的exports对象===该模块下的module.exports属性
    一旦改写(不是添加)exports或module.exports,他们就没有指向关系了,所以尽量只是添加,不要改变他们的指向关系

    process对象

    process是全局对象

    stdin/stdout: 标准输入输出流(IO)

    stdin和stdout提供了操作输入和输出数据的方法,通常也被称为IO操作

    Buffer类

    Buffer类用于操作二进制数据流
    当为buffer对象分配空间大小后,长度是固定的,不能更改
    可以修改长度内的数据,但不能添加数据
    length指的是字节长度,不是字符串的长度

    • new Buffer(size);创建一个buffer对象并为这个对象分配一个大小,size为数据类型
    var bf = new Buffer(5);
    console.log(bf);//<Buffer 88 f3 30 00 02>→打印出来的是16进制数据,数据随机
    bf[6]=8;
    console.log(bf);//<Buffer 88 f3 30 00 02>→没有出现第6位数
    bf[0]="8";
    console.log(bf);//<Buffer 08 f3 30 00 02>→第一个数被改写
    
    • new Buffer(array);创建一个buffer数组
    var bf = new Buffer(["ab","2",4]);
    console.log(bf);//<Buffer 00 02 04>
    bf[6]=8;
    console.log(bf);//<Buffer 00 02 04>→同样不能添加数据
    bf[0]="8";
    console.log(bf);//<Buffer 08 02 04>→同样可以改写数据
    
    • new Buffer(string,[encoding]);创建一个buffer对象
    var bf = new Buffer("hua","utf-8");
    console.log(bf);//<Buffer 68 75 61>→16进制
    for (var i=0; i<bf.length;i++){
        console.log(bf[i]);//打印出来的是2进制
        console.log(String.fromCharCode(bf[i]));//将编码转换成字符串
    }
    // 104
    // h
    // 117
    // u
    // 97
    // a
    

    buffer.write()方法

    buffer对象.write(要写入到buffer对象的字符串[,从buffer对象的第几位开始写入][,写入的字符串长度],[写入的字符串的编码]);

    buffer.slice()和buffer.copy()方法

    相同点:都是截取一个buffer对象,获得一个新的buffer对象
    不同点:使用slice,改变新buffer的数据会同时改变原buffer数据;copy就不会

    var str="caihua";
    var bf=new Buffer(str);
    console.log(bf);//<Buffer 63 61 69 68 75 61>
    var bf1=new Buffer(5);
    console.log(bf1);//<Buffer 00 00 00 00 38>
    var bf2=bf.copy(bf1,1,2,3);
    console.log(bf1);//<Buffer 00 69 00 00 38>
    console.log(bf2);//1,返回的是写入到新bf1的长度
    

    File System文件系统模块

    该模块是核心模块,需要使用require方法导入fs模块后使用
    该模块提供了操作文件的一些API

    fs.open(path,flags,[mode],callback)

    path:要打开的文件路径
    flags:打开文件的方式,读/写
    mode:设置文件的模式,读/写/执行,对应4/2/1
    callback:回调函数
      err:文件打开失败的错误提示保存在err里,打开成功err为null
      fd:被打开文件的标识

    举个栗子

    var projectData={
        "name":"caihua",
        "fileData":[
            {
                "name":"css",
                "type":"dir"
            },{
                "name":"js",
                "type":"dir"
            },{
                "name":"index.html",
                "type":"file",
                "content":"<html>
    	<head>
    		<title>title</title>
    	</head>
    	<body>
    		<h1>caihua is nice</h1>
    	</body>
    </html>"
                //
    是折行,	是缩进
            }
        ]
    };
    var fs=require("fs");
    if(projectData.name){
        fs.mkdirSync(projectData.name);
        var fileData=projectData.fileData;
        if(fileData && fileData.forEach){//如果fileData存在,并且它是数组,有forEach方法
            fileData.forEach(function(f){//f是数组fileData里的每一个对象
                f.path=projectData.name+"/"+f.name;//构建一个完整的目录
                f.content=f.content||"";//避免没有content时出错
                switch(f.type){
                    case "dir":
                        fs.mkdirSync(f.path);
                        break;
                    case "file":
                        fs.writeFileSync(f.path,f.content);
                        break;
                    default:
                        break;
                }
            })
        }
    

    合并文件,举个栗了

    var fs=require("fs");
    var filedir="./test";//要合并内容的文件夹
    fs.watch(filedir,function(ev,file){//监听要合并内容的文件夹里的内容
        fs.readdir(filedir,function(err,datalist){//读取该文件夹下的内容
            //datalist是一个数组,用来装该文件夹下的文件名
            var arr=[];//用来装要合并内容的文件的路径
            datalist.forEach(function(f){
                if(f){
                    var info=fs.statSync(filedir+"/"+f);//参数是路径
                    if(info.mode==33206){
                        arr.push(filedir+"/"+f);
                    }
                }
            });
            var content="";//用来装该文件夹下每个文件的内容
            arr.forEach(function(f){
                var c=fs.readFileSync(f);
                content+=c.toString()+"
    ";
            });
            fs.writeFile("./index.js",content);
        })
    });
    

    用到的方法:

    1. fs.watch(文件夹所在路径,回调函数)→监听文件夹内的变化
    2. fs.readdir(文件夹所在路径,回调函数)→读取文件夹下所有文件
    3. fs.statSync(文件所在路径)→读取文件详情
    4. fs.readFileSync(文件所在路径)→读取文件内容,得到的是buffer对象,二进制,可以用toString方法转成字符串, 是换行
    5. fs.writeFile(要写入内容的文件的路径,要写入的内容)→写入内容

    使用node进行web开发

    1. 用户通过浏览器发送http请求到指定的主机(服务器)
    2. 服务器接收请求,处理请求
    3. 服务器处理完成,返回对应的数据到用户机器(浏览器)
    4. 浏览器接收数据并进行分析和处理

    浏览器即客户端,服务器就是服务端,请求过程就是两台机器之间的数据通信,即两台机器的交互过程
    要进行web开发,必须搭建一个服务器来接收来自任何客户端的链接和请求,并进行对应的处理
    nodejs中可以通过http模块来搭建服务器(非nodejs的核心模块)

    http模块

    用到的方法

    1. http.createServer(回调函数);→创建并返回一个web服务器对象。
    2. server.listen(port,[hostname,][backlog,][callback])→listen方法可以用来设定监听哪个网卡的哪个端口的数据。
    3. server.address();→{ address: '::', family: 'IPv6', port: 9960 }→获取服务器地址,address不设置,默认监听所有网卡过来的数据;端口可以由node自动分配,每刷新一次,端口会变,所以建议手动设置端口。端口不能随意设置,1-1024之间的端口号已经被约定给系统或应用程序等使用(ipachy监听的端口号是80,ftp监听的端口号是21),所以建议将端口设置大一点
    4. server.on("error",function(err){});→该方法是为了预防端口设置错误,当端口设置错误时触发。
    5. server.on("listening",function(){});→当端口设置正确时触发。
    6. server.on("request",function(){});→当向该地址的该端口发送请求时触发。
      7.http.STATUS_CODES;→是一个对象,全部的标准http响应状态码的集合和简短描述。

    端口的概念

    网卡是一个数据交互的大通道,如果没有端口,任意程序可以监听网卡上的任意数据,会造成混乱,于是诞生了端口。网络数据交互的程序只能监听从对应端口进入的数据,一个应用程序可以监听多个端口的数据,一个端口的数据只能被一个应用程序监听

    request请求

    1. server.on("request",function(){})的request事件其实就是http.createServer(回调函数)里的回调函数,函数有两个参数request和response。request提供了一个客户端信息对象,会存储和客户端发送的请求有关的信息;response则提供了一个服务端信息对象,比如用来处理服务端向客户端发送的数据。
    2. request和response都是http对象的实例

    request对象包含的重点内容

    • httpVersion:使用的http版本信息,一般为1.1
    • headers:请求头信息中的数据
    • url:请求的地址
    • method:请求方式

    response对象包含的重点内容

    • write(chunk,[encoding]):发送一个数据块到响应正文中。
    • end([chunk,][encoding]):当所有的正文和头信息发送完了后调用该方法告诉服务器,数据已发送完成。这个方法在每次发送完信息后必须调用,且是在最后调用。
    • statusCode:该属性用来设置返回的状态码
    • setHeader(name,value):设置返回头信息
    • writeHead(statusCode,[reasonPhrase],[headers]):这个方法只能在当前请求中使用一次

    用户发送http请求→服务器响应并处理数据→返回给客户端→客户端接收数据并进行处理

    url模块

    url.parse(路径名);→将url解析成一个对象,方便调用

    举个栗子

    var http=require("http");
    var url=require("url");
    var server=http.createServer();
    server.listen(8080,"localhost");
    server.on("request",function(req,res){
        var urlStr=url.parse(req.url);
        switch (urlStr.pathname){
            case "/":
                //首页
                res.writeHead(200,{
                    "content-type":"text/html;charset=utf-8"
                });
                res.end("<h1>这是首页</h1>");
                break;
            case "/users":
                //用户页面
                res.writeHead(200,{
                    "content-type":"text/html;charset=utf-8"
                });
                res.end("<h1>这是用户页面</h1>");
                break;
            default:
                res.writeHead(404,{
                    "content-type":"text/html;charset=utf-8"
                });
                res.end("<h1>这是错误页面</h1>");
                break;
        }
    });
    

    使用fs模块实现行为表现分离

    用到的方法和属性

    1. __dirname是全局变量。在任何模块文件内部,可以使用__dirname变量获取当前模块文件所在目录的完整绝对路径。
    2. fs.readFile(file,function(err,data){});→读取文件内容
  • 相关阅读:
    Docker从入门到精通(四)——常用命令
    Docker从入门到精通(二)——安装Docker
    Docker从入门到精通(一)——初识
    Java设计模式之(十三)——模板方法模式
    Java设计模式之(十四)——策略模式
    Docker从入门到精通(七)——容器数据共享
    YCFramework版本更新:V1.0.2
    YCFramework版本更新:V1.0.3
    我的分布式微服务框架:YCFramework
    mysql 多表多字段报表填充查询
  • 原文地址:https://www.cnblogs.com/giselle527/p/6601030.html
Copyright © 2011-2022 走看看