Node.js第一遍学习

https://nqdeng.github.io/7-days-nodejs/

  • cmd模块系统

    使用require、exports、module三个预先定义好的变量。⚠️和ES6的import、export分开。
    require用于传入一个模块名,返回一个模块导出对象。可以./开头引入相对路径,也可以/或盘符:开头引入绝对路径,还可以直接foo/bar,类似关键词搜索。文件扩展名(后缀)可省略。例:var foo1 =  require('./foo');
    exports导出当前模块里的对象 例:exports.hello = function () { console.log('hello world!'); }
    module.exports对象是由模块系统创建的,可以通过改变它来改变当前模块的默认导出对象。例如:
     
    module.exports = function () {
        console.log('Hello World!');
    };
    模块默认导出对象变成一个函数。
    ⚠️module.exports的赋值必须立即执行。不能再任何回调中执行。
    模块初始化:一个模块中的JS代码仅在模块第一次被使用时执行一次,并在执行过程中初始化模块的导出对象。之后,缓存起来的导出对象被重复利用。也就是说第一次require后导出对象被缓存,第二次require该对象无用无影响.
     
  • 模块路径解析规则

  1. 内置模块
    如果给require传入的是NodeJS内置模块名称,不做路径解析,直接返回内部模块的导出对象,例require('fs');
  2. node_modules目录:用于存放模块。查找规则:基于本目录进行由下向上查找。
  3. NODE_PATH环境变量:可通过其指定额外的模块搜索路径。可包含多个路径。linux 用:分隔。windows用;分隔。加载模块时会依次尝试。
     
  • 很多子模块组成的大模块称作包。物理上就是文件夹下面有很多js文件,这个文件夹就可以被称作包。每个包都需要一个入口模块。入口模块的导出对象被作为包的导出对象。
    可以在包下的pakage.json中定义包名和入口文件:
    { "name": "cat", "main": "./lib/main.js" }   这样就可以在外面用require('/home/user/lib/cat')的方式引用cat包。主要目的是不出现入口文件main.js的引用。

     
  • 命令行程序:自制脚本

  1. 在脚本第一行: #! /usr/bin/env node
  2. 给文件执行权:chmod +x /home/user/bin/node-echo.js
  3. 在PATH环境变量中指定的某个目录下,建立软链接文件,文件名与我们希望使用的终端命令同名:  sudo ln -s /home/user/bin/node-echo.js /usr/local/bin/node-echo


     
  • 工程目录


    main可能写错了,指向编译后的最上层的入口文件。

     
  • 发布代码

    第一次使用NPM发布代码前需要注册一个账号。终端下运行npm adduser,之后按照提示做即可。

    常用npm命令
    • NPM提供了很多命令,例如installpublish,使用npm help可查看所有命令。

    • 使用npm help <command>可查看某条命令的详细帮助,例如npm help install

    • package.json所在目录下使用npm install . -g可先在本地安装当前命令行程序,可用于发布前的本地测试。

    • 使用npm update <package>可以把当前目录下node_modules子目录里边的对应模块更新至最新版本。

    • 使用npm update <package> -g可以把全局安装的对应命令行程序更新至最新版。

    • 使用npm cache clear可以清空NPM本地缓存,用于对付使用相同版本号发布新版本代码的人。

    • 使用npm unpublish <package>@<version>可以撤销发布自己发布过的某个版本代码。

  • 文件

    • 文件拷贝:
      1. 小文件:
      2. 大文件:
    • API简介 
      1. Buffer(数据块):二进制
        1. NodeJS提供了一个与String对等的全局构造函数Buffer来提供对二进制数据的操作。
        2. 除了可以读取文件得到Buffer的实例外,还能够直接构造:var bin = new Buffer([ 0x68, 0x65, 0x6c, 0x6c, 0x6f ]); //可用.length 和 bin[0]
        3. 可与字符串转化:var str = bin.toString('utf-8');   var bin = new Buffer( 'hello', 'utf-8');
        4. 与string的区别:
          1. 字符串只读,并且对字符串的任意修改得到的都是新字符串,原字符串保持不变。而buffer类似指针数组。
          2. .slice也不是返回新buffer,而是指向某位置。因此对.slice返回的buffer做修改会影响到原buffer
          3. 因此,要想不对原buffer有影响,要先申请一块内存,再将原有拷贝过去: var dup =  new Buffer(bin.length); bin.copy(dup); //感觉和c的指针数组一毛一样
      2. Stream(数据流):例如大文件拷贝,当内存中无法一次装下需要处理当数据时,或者一边读一边处理更高效时,就需要用到数据流。
        1. 只读流
        2. 只写流
        3. .pipe也是做类似的防爆仓控制,它的内部实现方式与上边的代码类似
      3. File System(文件系统):对文件进行操作。fs模块提供的API基本上可以分为一下三类:
        1. 文件属性读写: fs.stat、fs.chmod、fs.chown等
        2. 文件内容读写:fs.readFile、fs.readdir、fs.writeFile、fs.mkdir等
        3. 底层文件操作:fs.open、fs.read、fs.write、fs.close等
        4. 上边提到的这些api都是通过回调函数传递结果。以fs.readFile为例:
        5. 每个异步api都对应一个同步版本。末尾+Sync,异常对象和执行结果的传递方式也不同,如上。
      4. Path(路径):
        1. path.normalize: 将传入的路径转换为标准路径,能解析.和..还能去掉多余的斜杠。如path.normalize( 'foo//baz//../bar' ) => 'foo/bar'
          ⚠️⚠️⚠️ windows是\,linux是/ 。如果想保证任何系统下都是用/作为路径分隔符的话,需要用.replace(/\\/g, '/') 在替换下标准路径。
        2. path.join: 将传入的多个路径拼接为标准路径,并且能在不同系统下正确使用相应分隔符。例:path.join( 'foo/', 'baz/', '../bar' ); => 'foo/bar'
        3. path.extname:获得文件的扩展名。例: path.extname(' foo/bar.js ');  => '.js'
           
    • 遍历算法
      1. 递归 :最好转化成循环
      2. 目录遍历:树的先序遍历:根左右
      3. 同步遍历:
      4. 异步遍历:


         
    • 文本编码
      1. 要把文件内容换为js使用的UTF-8,可用文本文件头的几个字节来判断文件是否包含BOM,以及使用的是哪种编码。一般要去掉BOM
      2. 识别和除去UTF8 BOM:
      3. GBK转UTF8: 借助第三方包iconv-lite来转换编码
      4. 单字节编码:中文→ 乱码 → 中文 ,只要按照相同规则中文前后不会变

       
  • 网络操作

    • http模块提供两种使用方式:
      1. 作为服务端使用:创建一个http服务器,监听http客户端请求并返回响应。
        1. http请求和响应数据内容
        2. 处理请求示例
        3. 编辑发送响应示例
      2. 作为客户端使用:发起一个http客户端请求,获取服务端响应。
        1. 编辑发起请求示例
        2. 通过回调函数处理响应示例(简化get/post等方法,提供了更简单的api)
    • https:https模块与http模块极为类似,区别在于https模块需要额外处理SSL证书。
      1. 创建https服务器
      2. 客户端编辑发起请求:
    • url
      1. 组成:
      2. parse方法可将一个url字符串转换为url对象。(参数可以不完整)
        url.parse('http://user:pass@host.com:8080/p/a/t/h?query=string#hash');
      3. format方法允许将一个url对象转换为url字符串
        url.format({ protocol: 'http:', host: 'www.example.com', pathname: '/p/a/t/h', search: 'query=string' });
      4. resolve 拼接url
        url.resolve('http://www.example.com/foo/bar', '../baz');
    • query string
      • querystring.parse('foo=bar&baz=qux&baz=quux&corge'); => { foo: 'bar', baz: ['qux', 'quux'], corge: '' }
      • querystring.stringify({ foo: 'bar', baz: ['qux', 'quux'], corge: '' }); => 'foo=bar&baz=qux&baz=quux&corge='
    • Zlib :数据压缩和解压的功能



      •  
    • net:net模块可用于创建Socket服务器或Socket客户端

      •  

      •  
    • 使用NodeJS操作网络,特别是操作HTTP请求和响应时会遇到一些惊喜,这里对一些常见问题做解答。

      • 问: 为什么通过headers对象访问到的HTTP请求头或响应头字段不是驼峰的?

        答: 从规范上讲,HTTP请求头和响应头字段都应该是驼峰的。但现实是残酷的,不是每个HTTP服务端或客户端程序都严格遵循规范,所以NodeJS在处理从别的客户端或服务端收到的头字段时,都统一地转换为了小写字母格式,以便开发者能使用统一的方式来访问头字段,例如headers['content-length']

      • 问: 为什么http模块创建的HTTP服务器返回的响应是chunked传输方式的?

        答: 因为默认情况下,使用.writeHead方法写入响应头后,允许使用.write方法写入任意长度的响应体数据,并使用.end方法结束一个响应。由于响应体数据长度不确定,因此NodeJS自动在响应头里添加了Transfer-Encoding: chunked字段,并采用chunked传输方式。但是当响应体数据长度确定时,可使用.writeHead方法在响应头里加上Content-Length字段,这样做之后NodeJS就不会自动添加Transfer-Encoding字段和使用chunked传输方式。

      • 问: 为什么使用http模块发起HTTP客户端请求时,有时候会发生socket hang up错误?

        答: 发起客户端HTTP请求前需要先创建一个客户端。http模块提供了一个全局客户端http.globalAgent,可以让我们使用.request.get方法时不用手动创建客户端。但是全局客户端默认只允许5个并发Socket连接,当某一个时刻HTTP客户端请求创建过多,超过这个数字时,就会发生socket hang up错误。解决方法也很简单,通过http.globalAgent.maxSockets属性把这个数字改大些即可。另外,https模块遇到这个问题时也一样通过https.globalAgent.maxSockets属性来处理。



       
  • 进程
    • API
      1. process: 可以感知和控制nodejs自身进程的方方面面。不是内置模块,而是一个全局对象,因此在任何地方都可以直接用。
      2. child_process: 创建和控制子进程,该模块最核心的api是.spawn。其余api都是针对特定使用场景对他的进一步封装,算是一种语法糖。
      3. cluster:对child_process的进一步封装,专用于解决单进程nodejs web服务器无法充分利用多核cpu的问题。使用该模块可以简化多进程服务器程序的开发,让每个核上运行一个工作进程,并统一通过主进程监听端口和分发请求。
    • 获取命令行参数: process.argv.slice(2);
    • 退出程序: try{ //... } catch (err) { process.exit(1) };  正常退出: process.exit(0);
    • 控制输入输出:
      • 标准输入流: process.stdin 只读数据流
      • 标准输出流:process.stdout 只写数据流
      • 标准错误流:process.stderr 只写数据流
      • 实现console.log :

         
    • 降权:在Linux系统下,我们知道需要使用root权限才能监听1024以下端口。但是一旦完成端口监听后,继续让程序运行在root权限下存在安全隐患,因此最好能把权限降下来。
      • ⚠️ 
        1. 如果是通过sudo获取root权限的,运行程序的用户UID和GID保存在环境变量SUDO_UID和SUDO_GID里边。如果是通过chmod+s方式获取root权限的,运行程序的用户UID和GID可直接通过process.getuid和process.getgid方法获取。
        2. process.setuid和process.setgid方法只接受number类型的参数。
        3. 降权必须先绛gid再绛uid
    • 创建子进程
      • child_process.spawn(command[, args][, options])  第一个参数可以是路径也可以是path环境变量能找到的执行文件名(命令名) 第二个是命令行参数数组。第三个可选用于配置子进程的执行环境与行为
      • 另外,上例中虽然通过子进程对象的.stdout.stderr访问子进程的输出,但通过options.stdio字段的不同配置,可以将子进程的输入输出重定向到任何数据流上,或者让子进程共享父进程的标准输入输出流,或者直接忽略子进程的输入输出。
    • 进程间通讯
      • //父进程在创建子进程时,在options.stdio字段中通过ipc开启了一条ipc通道
        //之后就可以监听子进程对象的message事件接受来自子进程的消息,并通过.send方法给子进程发送消息。
        //在子进程这边,可以在process对象上监听message事件接收来自父进程的消息,并通过.send方法向父进程发送消息。
        //数据在传递过程中,会先在发送端使用JSON.stringify方法序列化,再在接收端使用JSON.parse反序列化

    • 守护子进程
      • 监控工作进程的运行状态,在工作进程不正常退出时重启工作进程,保障工作进程不间断运行。
  • 异步:
    • 串行异步: 数组成员一个接一个执行:
    • 并行异步: 数组成员可以并行,但后续代码需要所以数组成员处理完毕后才能执行。
    • 异常:
      • 普通的try catch只能捕获同步代码中的异常。异步函数会打断代码执行路径,异步函数执行过程中以及执行之后产生的异常冒泡到执行路径被打断的位置时,如果一直没有遇到try语句,就会作为一个全剧异常抛出。
      • 异步异常的正确捕获方式
      • 对于接连有多个异步的异常捕获,如果按上述写法,回调嵌套使得代码层级会很深,因此node推出以下解决方案。
        • 可以通过process对象捕获全局异常
          process.on('uncaughtException', function (err) {
              console.log('Error: %s', err.message);
          });
        • 如果想尽早捕获,可以使用域(domain)。
        • 用域:
        • ⚠️无论是通过process对象的uncaughtException事件捕获到全局异常,还是通过子域对象的error事件捕获到了子域异常(回调),捕获异常后强烈简易立即重启程序,try一般不用。
  • 大示例
    • 静态文件合并服务器,该服务器需要支持类似以下格式的JS或CSS文件合并请求。

      http://assets.example.com/foo/??bar.js,baz.js

      在以上URL中,??是一个分隔符,之前是需要合并的多个文件的URL的公共部分,之后是使用,分隔的差异部分。因此服务器处理这个URL时,返回的是以下两个文件按顺序合并后的内容。

      /foo/bar.js
      /foo/baz.js

      另外,服务器也需要能支持类似以下格式的普通的JS或CSS文件请求。

      http://assets.example.com/foo/bar.js

      以上就是整个需求。

      working/node/example_server.js

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
本火锅店点餐系统采用Java语言和Vue技术,框架采用SSM,搭配Mysql数据库,运行在Idea里,采用小程序模式。本火锅店点餐系统提供管理员、用户两种角色的服务。总的功能包括菜品的查询、菜品的购买、餐桌预定和订单管理。本系统可以帮助管理员更新菜品信息和管理订单信息,帮助用户实现在线的点餐方式,并可以实现餐桌预定。本系统采用成熟技术开发可以完成点餐管理的相关工作。 本系统的功能围绕用户、管理员两种权限设计。根据不同权限的不同需求设计出更符合用户要求的功能。本系统中管理员主要负责审核管理用户,发布分享新的菜品,审核用户的订餐信息和餐桌预定信息等,用户可以对需要的菜品进行购买、预定餐桌等。用户可以管理个人资料、查询菜品、在线点餐和预定餐桌、管理订单等,用户的个人资料是由管理员添加用户资料时产生,用户的订单内容由用户在购买菜品时产生,用户预定信息由用户在预定餐桌操作时产生。 本系统的功能设计为管理员、用户两部分。管理员为菜品管理、菜品分类管理、用户管理、订单管理等,用户的功能为查询菜品,在线点餐、预定餐桌、管理个人信息等。 管理员负责用户信息的删除和管理,用户的姓名和手机号都可以由管理员在此功能里看到。管理员可以对菜品的信息进行管理、审核。本功能可以实现菜品的定时更新和审核管理。本功能包括查询餐桌,也可以发布新的餐桌信息。管理员可以查询已预定的餐桌,并进行审核。管理员可以管理公告和系统的轮播图,可以安排活动。管理员可以对个人的资料进行修改和管理,管理员还可以在本功能里修改密码。管理员可以查询用户的订单,并完成菜品的安排。 当用户登录进系统后可以修改自己的资料,可以使自己信息的保持正确性。还可以修改密码。用户可以浏览所有的菜品,可以查看详细的菜品内容,也可以进行菜品的点餐。在本功能里用户可以进行点餐。用户可以浏览没有预定出去的餐桌,选择合适的餐桌可以进行预定。用户可以管理购物车里的菜品。用户可以管理自己的订单,在订单管理界面里也可以进行查询操作。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值