美文网首页
三、node(一)

三、node(一)

作者: sheepmiee | 来源:发表于2017-02-24 23:50 被阅读70次

    Node的安装

    把NODE安装后,如果我们没有修改安装的目录,那么默认是安装在:C:\Program Files\nodejs (大部分都是,如果自己修改了安装目录,自己去查找即可)

    如果我们安装了NODE,那么它默认会把命令集成到DOS命令中,也就是DOS窗口中可以执行NODE命令

    如果没有集成到DOS中,说明环境变量中缺少执行的文件,需要我们配置环境变量:

    [WIN7]配置环境变量
    我的电脑(右键) -> 高级系统设置 -> 环境变量

    系统变量 -> Path -> 把原有的变量值保存一份

    把NODE安装的目录添加到原有值的后面,例如:...;C:\Program Files\nodejs\

    在把最新的结果重新写入到环境变量值中

    Node的基本信息

    何为NODE

    NODE其实并非后台开发语言,我们了解的JAVA、PHP、C#、.NET(dot net)...才是后台开发语言,NODE仅仅是一个工具,一个基于V8引擎来渲染和解析JS的平台和工具(有点类似浏览器)
    真实的开发中,我们一般都把NODE安装在服务器端,这样我们就可以在服务器端编写一些JS代码来处理服务器端的业务逻辑了 =>JS不仅仅可以在客户端浏览器中运行处理客户端业务逻辑(前端开发语言),也可以在服务器端的NODE环境下运行处理服务器端业务逻辑(后台开发语言),所以JS是全栈开发语言

    NODE如何去执行JS代码

    • 直接利用WB:在JS的空白处,右键,找到 Run xxx.js 就是在WB中调取NODE环境执行我们的JS代码
    • 在当前JS所在的文件目录中打开DOS窗口,在DOS中执行 node xxx.js 也相当于把JS代码在NODE环境下执行了
    • NODE的REPL命令:打开命令行输入node,出现 ‘ > ’说明已经进入了REPL

    REPL(Read-Eval-Print Loop,简称REPL,“读取-求值-输出”循环)是一个简单的,交互式的编程环境。
    REPL既可以作为独立单机程序,也可以被其他的程序包含在内的程序。
    它提供了一种交互方式,即“执行程序,展现结果”。
    它可以被用作debugging,testing 或者只是执行操作得到一些结果。

    NODE的优势

    • 快:基于V8引擎渲染和解析的
    • NODE是单线程基于事件驱动的异步操作
    • NODE提供了无阻塞的I/O操作

    I/O:input/output 对文件的增删改查操作

    • JS在客户端浏览器中运行的时候是不能对客户端本地的文件进行I/O操作的,因为我们要保证客户端的安全,JS做为前端开发语言是不可以操作客户端本地文件的,但是浏览器也提供了部分需要用户自主操作的功能,例如:上传图片
    • JS在服务器端NODE环境下运行的时候可以对服务器上的文件进行I/O操作

    学习NODE从模块开始

    • 内置模块:自身带的 http、url、fs等
      http:提供HTTP服务器功能
      url:用于解析URL
      fs:操作文件系统
    • 自定义模块:自己写的模块
    • 第三方模块:别人写好的,我们来调取使用
      安装NODE之后自带npm命令,用来管理第三方模块的
      所有我们需要调取的第三方模块都在https://www.npmjs.com/这个网站中

    使用npm安装模块
    1、安装到全局(global)
    npm install xxx(模块名字) -g
    npm uninstall xxx -g 卸载已经安装在全局的模块

    2、安装在当前的项目下
    npm install xxx(模块名字)

    npm uninstall xxx 
    

    把模块安装到全局的问题:

    • 以后不管是在哪一个项目目录下,我们都可以"通过使用命令操作的方式"来进行操作了,但是不能通过代码导入这个模块使用
    • 安装在全局有很多时候会导致版本号冲突,例如:我之前安装的是LESS的2.7版本,以前的项目都是使用这个版本开发的,后来LESS升级了,升级到3.1,新版本和之前的版本不太一样,如果全局安装最新的,原来的项目就没办法使用LESS了

    把模块安装在当前的项目中也有问题:

    • 不能像安装在全局一样使用命令了,但是可以使用JS导入了
      解决办法:在package.json 文件的scripts这个属性中进行配置
      "scripts": {//->配置NPM脚本命令
      "myFirst": "lessc ceshi.less ceshi.min.css -x"
      }
      以后再DOS中只需要执行npm run myFirst,就可以执行lessc -v这个命令了
    • 在当前的项目中会有一个node_modules文件夹,里面存储的都是我们当前项目所需要使用的模块(这个文件夹很大的,传递给其他人非常的不好处理)
      解决办法:上传gitHub的时候在项目目录中增加一个文件:.gitignore 这个文件中可以配置上传的时候忽略哪些文件,这些被忽略的文件就不在上传了
    • 我们把一些第三方模块安装在A项目下,B项目不能直接的导入使用,如果需要的话还需要在B项目中重新的安装一遍
      解决办法:需要在安装第三方模块的时候,把当前项目的所需要的模块清单写入到package.json的开发依赖项中
      npm install xxx --save-dev 放在开发依赖模块清单中
      npm install xxx --save 放在生产依赖的模块清单中
      下一个B项目如果还是需要这些模块,我们就没有必要一个个的安装了,只需要把package.json文件拷贝到B项目中,然后执行 npm install 即可,这样的系统就会默认按照我们的开发依赖清单一个个的下载 =>"跑环境"

    我们平时在做项目开发的时候,首先会在当前项目的根目录下执行:
    npm init -y
    这样执行完成后,会在当前项目的根目录下生成一个文件:

            package.json       
         {
         "name": "20170222", //->项目名称
         "version": "1.0.0", //->项目的版本号
         "description": "", //->当前项目的描述
         "main": "temp.js", //->当前项目的入口
         "dependencies": {  //->当前项目依赖的第三方模块清单(生产:项目发布上线)
           "less": "^2.7.2"
         },
         "devDependencies": {}, //->当前项目依赖的第三方模块清单(开发:项目正在研发)
         "scripts": {//->命令脚本
         "test": "echo \"Error: no test specified\" && exit 1"
         },
         "keywords": [],
             "author": "",
         "license": "ISC"
         }
    
    • 模块间的相互调用
      在NODE环境下,它认为每一个JS都可以理解为一个单独的模块,所以我们创建模块只需要创建JS文件即可;并且每一个模块和模块之间是互不干扰的,同时模块之间也可以通过特定方法相互调用一些语句

    调用内置模块
    require('http')//与导入自定义模块略有不同,参数内不需要有文件路径
    require('url')
    require('fs')

    自定义模块 B模块调用A模块的sum方法:
    A.js:
    function sum() {...}
    module.exports = {//此对象中的方法可为其他模块导入使用
    sum: sum
    };

        B.js:
        var a = require('./A');//代码导入A模块,可以使用A模块中module.exports中的方法,'./'为导入的模块的路径,表示当前目录,'A为导入模块的名字'
        a.sum();//调用A模块中的sum函数
    

    NODE中的内置模块

    服务器端需要处理的事情
    + 在服务器上创建一个服务(监听一个端口)
    + 接收(解析)客户端的请求信息
    + 找到客户端需要的资源文件中的源代码
    + 把源代码返回给客户端

    • HTTP 这个模块主要用于创建服务、监听端口、接收请求、返回内容的管理;

    http.createServer([callback]):创建服务,默认遵循的是http传输协议
    [callback]:此处的callback并不是当服务创建成功和=后就执行的,而是要等到客户端项向当前的服务发送请求时才会被触发,而且每次发送请求都会被触发,我们需要在这个回调函数中完成:接收解析、资源查找、源代码返回等操作

        客户端如何迪昂当前服务发送请求?
    
        http://localhost:8080/
        向本地8080端口对应的服务发送请求
    
        http://本机的ip地址:8080/
        通过服务器的ip地址(外网ip,局域网ip)向当前服务器的8080服务发送请求
    
        不仅会触发callback,还默认传递了2个参数:function(req.res){}
        - req:request 请求对象,里面有很多属性和方法,存储了客户端的全部请求信息
            + req.url:储存的是客户端请求的资源文件路径以及问号传参的值,如:/css/index.css?name=zxt&age=27(字符串)
        - res:response 响应对象,里面提供了很多方法,可供服务器把源代码返回给客户端
            + res.write([content]);向客户端响应内容(响应的内容是字符串)
            + res.end(); 结束向客户端的响应
            + res.writeHead;重写响应头
    

    listen([port],[callback]):监听端口
    [port]:端口号,取值范围0到65535,需要保持端口号的唯一性
    [callback]:服务创建成功后,会执行这个回调函数,一般我们会输出一句话提示开发者创建成功
    @return:类型,作用
    例如
    var http = require('http');
    var server = http.createServer();
    server.listen(80,function () {
    console.log('success');
    });

    • URL 主要用来解析URL地址的
      url.parse():解析一个完整的url(也可以不完整)的每一项

    例如:

        var url = require('url');
        var str = "http://www.zhufengpeixun.cn:80/school/login.html?a=12$b=13#c"
        cosnole.log(url.parse(str,true));
    
        结果:
        Url {
          protocol: 'http:',
          slashes: true,
          auth: null,
          host: 'www.zhufengpeixun.cn:80',
          port: '80',
          hostname: 'www.zhufengpeixun.cn',
          hash: '#c',
          search: '?a=12&b=13',
          query: { a: '12', b: '13' },//第二个参数true会把问号传参解析成对象
          pathname: '/school/login.html',
          path: '/school/login.html?a=12&b=13',
          href: 'http://www.zhufengpeixun.cn:80/school/login.html?a=12&b=13#c' }
    
    • FS
      提供一些方法供开发者进行I/O操作

      fs.readFileSync([pathname]):同步读取文件中的内容,读取出的内容是字符串
      fs.readFile([pathname][callback]):异步读取文件的内容
      fs.writeFileSync([pathname],[content]):同步把内容写入到文件中,写入的内容需要是字符串格式,而且写入属于覆盖式写入
      fs.writeFile

    静态资源文件请求处理(HTML/CSS/JS/IMG(PNG、JPG、GIF...)/TXT...)

    • 所有的静态资源文件都有一个共同的特征:都有后缀名,后缀名是由字母和数字组成的
    • 分析规律得到,服务器端需要查找文件的路径地址只是在pathname前面加一个点即可
    • 在客户端向我们的服务发送请求的时候,谷歌浏览器会默认请求一个图片"favicon.ico",但是在我们的服务器上是没有这张图片的,所以在使用FS查找内容的时候找不到,导致后台服务报错 =>如果客户端请求的资源文件在服务器上不存在,我们不能终止服务(不能让服务抛异常),只需要返回不存在即可
    • 在IE浏览器中有问题:服务器端返回给客户端的都是字符串格式的数据(不管是HTML/CSS/JS...),对于谷歌浏览器来说,它比较的智能,会自动识别当前代码是什么类型的代码,然后进行解析和渲染;但是IE浏览器比较的弱智,不能识别具体的文件类型,都当成字符串了;
      IE问题解决办法:在返回数据给客户端的时候,指定当前文件的MIME类型,告诉IE是什么类型的即可
      MIME:每一种资源文件都有自己对应的类型,这些类型统称为MIME
      * HTML -> text/html
      * CSS -> text/css
      * JS -> text/javascript
      * PNG -> image/png
      * ...

    例:

    //->导入需要的内置模块
    var http = require('http'),
        url = require('url'),
        fs = require('fs');
        
    //->创建服务监听端口
    var server = http.createServer(function (req, res) {//创建服务
        var urlObj = url.parse(req.url, true),//url解析,true参数表示将问号传参解析为对象
            pathname = urlObj.pathname,//解析后的请求文件路径
            query = urlObj.query;//解析后的问号传参对象
        //->客户端静态资源文件请求的处理
        var reg = /\.([0-9a-zA-Z]+)/i;
        if (reg.test(pathname)) {
            var conFile = null,
                status = 200;
            try {//容错处理,防止请求文件返回错误报错而阻塞代码执行
            conFile = fs.readFileSync('.' + pathname);
            } catch (e) {
                conFile = 'not found~';
                status = 404;
            }
            //->根据当前请求资源文件的后缀名,计算出文件的MIME类型
            var suffix = reg.exec(pathname)[1].toUpperCase(),//后缀名捕获
            suffixMIME = 'text/plain';//文件MIME类型默认为txt的
            switch (suffix) {
                case 'HTML':
                    suffixMIME = 'text/html';
                    break;
                case 'CSS':
                    suffixMIME = 'text/css';
                    break;
                case 'JS':
                    suffixMIME = 'text/javascript';
                    break;
            }
            //->在返回数据内容之前指定MIME类型(重写响应头)
            res.writeHead(status, {
                'content-type': suffixMIME + ';charset=utf-8;'
            });
            res.end(conFile);
        }
        });
        server.listen(8080);//监听端口

    相关文章

      网友评论

          本文标题:三、node(一)

          本文链接:https://www.haomeiwen.com/subject/mirgwttx.html