zoukankan      html  css  js  c++  java
  • 服务端 | Nodejs 学习笔记(一)

    Node.js 


    前言:
      2009年面世
      nodejs.org 官网
      https://www.npmjs.com/ 模块社区
      github.com 仓库
      stackoverflow.com  问答社区
      基于chrome浏览器V8引擎、C++语言编写的,本质上是Js的运行环境;
      可以解析js代码;
      提供系统级别的api:
        1、文件的读写
        2、进程的管理
        3、网络通信

    安装:
      linux 上安装nodejs
      mac 上安装node:
        升级到mac系统到最新;
        下载安装 xcode 集成开发环境;
        xcode-select -p 检查是否安装了xcode 如果返回一个路径,说明已经安装了;如果没有安装
        xcode-select --install
      安装python;
      安装homebrew 「是针对Mac下的套件管理器,相当于ubuntu下的apt-get,相当于CentOS下的yum
        homebrew 依赖于 ruby,如果安装不成功,尝试升级ruby版本;
        brew install node mongodb
      node -v
      安装 node 版本管理工具 n
      npm install -g n
        n的使用
        n 0.10.22
        n
    -- 用 nodejs 创建一个服务器;
    本质上是一个 javascript 的执行环境,只不过加上封装、web底层的处理,赋予了更多的能力;
    保存为server.js

     1 const http = require('http'); // 加载http模块,这个模块是由js编写的;指责是创建服务器,处理 http 相关任务
     2 const hostname = '127.0.0.1';
     3 const port = 3000;
     4 const server = http.createServer((req, res) => {
     5 // 通过 createServer 创建一个web服务器,有请求从监听的端口过来时,调用里边匿名的回调函数;req用来获取这次请求相关的信息,res告诉服务器,响应一些内容;
     6   res.statusCode = 200;
     7   res.setHeader('Content-Type', 'text/plain');
     8   res.end('Hell Frank,fighting ! 
    ');
     9 });
    10 
    11 server.listen(port, hostname, () => { // 让服务器在端口上监听请求;服务器就 ready 了,就可以收到任何来自3000端口的请求
    12   console.log(`Server running at http://${hostname}:${port}/`);
    13 });

    node server.js // 执行

    浏览器刷新 http://127.0.0.1:3000/ 

     

    Nodejs 环境 和 浏览器的执行环境的异同:

    (1)都可以正常的执行 js 代码
    (2)宿主 浏览器是 window; node中没有 window document,有process http 等模块,但是浏览器没有

    Node.js 的模块 与 Commonjs规范:

    之前的http 和 process 都是nodejs的模块;
    页面中有大量js引入时,尤其是有相互依赖的情况下,很容易被覆盖掉,方法被重写了,js天生缺少一种模块管理机制,来隔离实现不同功能的js片段,避免他们相互污染;
    为此我们经常采用命名空间的方式,把变量和函数限制到某个特定的作用域内,人肉约定一套命名规范来约束代码,从而保障代码的安全执行,比如jQuery中,有许多的变量和方法,必须通过$调用;
    commonjs 并不像 jquery 是一套具体实现某功能的库,他是一套规范,包括模块、包、系统、二进制、单元测试等等,来约定 javascript 怎么来组织,怎么编写,同时大部分标准也是在拟定和讨论之中的;
    首先把执行不同任务的代码块看做成一个独立的模块,每一个模块看作成一个独立的作用域,但并不是孤立的,可能存在某种依赖关系,对于一个模块可以分成三个部分:模块的定义、模块的标示、模块的引用;js规范。
    Nodejs借鉴 commonjs 模块组织的理念,实现了一套模块管理系统;

    模块的分类:
      核心模块、本地模块、第三方模块;


    Nodejs API

    url.parse() 解析url:

      url.format()

      url.resolve()

    querystring 解析参数:

      querystring.stringfy({name: 'frank', age: 19})  将参数对象序列化解析为参数字符串,默认用=链接key alue,&;

      querystring.parse() 将参数对象反序列化;三个参数('',  ',' , ':' , 0)

      querystring.escape(str)  参数转译

      querystring.unescape()   参数反转译

    http 知识填坑:

      网络通信协议,http客户端发起请求,创建端口;http服务器在端口监听客户端请求;http服务器向客户端返回状态信息和内容;

      (1)浏览器输入url,接下来发生了什么。。。

      -1-、chrome浏览器搜索自身的DNS缓存,看看自己的DNS缓存有没有 baidu.com 对应的ip地址缓存,或缓存有没有过期,该缓存有效时间约 1 分钟;

      「chrome://net-internals/#dns 可查看浏览器dns缓存」

      -2-、如没有,搜索操作系统自身的DNS缓存;

      -3-、如没有,读取本地 host 文件,找是否有 DNS 的配置项;

      -4-、如没有,浏览器发起一个 DNS 的系统调用,向宽带运营商发起域名解析请求;

        「 宽带运营商服务器查看本身缓存,看是否有配置项,是否过期,

        如果没有,运营商服务器 代替浏览器发起一个迭代DNS解析请求 ---> 万网等域名服务上返回 ip 地址,

        运营商服务器把返回的结果 -> 返回操作系统内核并缓存起来,操作系统内核把结果返回给浏览器,浏览器拿到了对应的ip地址,域名解析完成。    

      -5-、浏览器获得域名对应的 ip 地址后,发起经典的 HTTP “三次握手”;「TODO」

      「浏览器向服务器发起TCP连接请求,通过层层路由设备到达服务器端的网卡,然后进入到服务器内核的 TCP/IP 协议栈,经过防火墙的过滤,建立起TCP/IP连接;」

      -6-、 建立起 TCP/IP 连接之后,浏览器就可以向服务器发送 HTTP 请求了,

      -7-、 服务器接收请求后,根据路径参数,经过后端的一些处理之后,把处理的结果返回给浏览器,浏览器进行渲染出页面;

      (2)请求方法:

        GET : 读取;POST:提交数据; PUT:更新信息;DELETE:删除;HEAD;TRACE;

      (3)状态码:

        1xx : 请求已经发出,正在处理

        2xx : 成功接受 「200 客户端请求成功」

        3xx : 需要重定向 : TODO

        4xx : 客户端错误:

          400 客户端语法等错误,服务器不能理解  

          401 请求没有经过授权」「服务器收到请求,拒绝服务,可能是没有权限等」「请求资源不存在,也可能是url错了」

        5xx : 服务器端的错误: 「500服务器发生了不可预期的错误」「服务器当前不能处理该请求,可能过一段时间会恢复正常」

      (4)https 协议

        

        https 是基于 http,在 http 基础上增加了 SSL/TLS 握手、数据加密传输;

        专门用于处理加密访问;

        搭建https服务器时需要ssl证书;

        创建 https 服务器:

        

    Node HTTP 模块:

    (1)回调:

      回调是异步编程最基本的方法,对于nodejs,需要按照顺序执行异步逻辑时,采用后续传递的方式,将后续逻辑封装在回调函数中作为起始函数的参数,逐层嵌套;

    (2)同步 异步:

      同步就是执行一个任务,后一个任务等待前一个任务完成后开始执行,程序的执行顺序与任务的排列顺序有关;

      js中经典的异步: setTimeout setInterval

    (3)I/O  磁盘的读入 输出:

    (4)单线程 / 多线程:

    (5)阻塞 / 非阻塞:

    (6)事件: 浏览器中鼠标的点击,拖拽窗口,

    (7)事件驱动:

    (8)基于事件驱动的回调:

    (9)事件循环: eventloop 是个回调函数队列,单线程,先进先出

    关于“作用域” “上下文”  填坑:

      - 作用域:和调用函数、访问变量的能力有关;局部作用域可以访问全局作用域的变量和函数,全局的访问不到局部的;

      - 上下文: this 关键字有关,是调用当前可执行代码的引用;

        「上下文代表 this 变量的值和指向,决定一个函数被怎么调用,当一个函数被作为一个对象的方法调用的时候,this总是指向调用这个方法的对象; 」

        「JS中,this 表示当前函数的拥有者,通常把拥有者叫作“执行上下文”;

          this 是 js 的关键字,是函数运行时自动生成的内部对象;只能在函数内部使用;

          对于函数的上下文执行对象,需要依据当前的运行环境而定,在全局运行的上下文中,this指向全局对象,在函数内部,this取决于函数被调用的方式:如下

                       「 this指向pat对象;」

           「 全局调用,this指向全局对象,浏览器:window;node环境指向 global 」

           「 构造函数中使用this,this指向新购建好的对象,实例对象;」

      JS的函数存在概念:定义时的上下文,运行时的上下文,上下文是可以改变的。函数的方法 call()  apply() 可以改变上下文执行对象,可以在自定义上下文中执行函数

           「 运行时改变上下文:通过call 改变this上下文,在调用时,将 this 指向dog,实现继承;」

           「 定义时改变上下文:这种方法不是执行是改变this指向,定义时已经改变了指向;」

    event事件:

      node 事件没有冒泡、捕获等;

    var EventEmitter =  require('events').EventEmitter
    
    var life = new EventEmitter()
    life.setMaxListeners(11) // 默认监听不超过10个,否则报 warning
    life.on('eventname', function (who) { // 此时 on 可以用 addEventListener 替换
      console.log('给' + who+ '倒水')
    })
    
    lief.emit('eventname', '汉子') 
    lief.emit('eventname', '汉子') 返回一个布尔值,true,说明事件被监听过;

    Promise

    异步的解决方案:

    (1)回调

    (2)事件机制

    (3)对事件增加事件监听,对某个异步操作增加异步触发,

    (4)订阅者发布者 的 观察者模式

    (5)promise 

    Promise A 与 Promise A+规范:

      

      promise库:bluebird

     promise重构网站爬虫:「待续」

      


     Nodejs 中的网络模块 - NET:

    互联网的价值基础是数据传送,一起都围绕数据展开,比如发送、接受等,但这一切都离不开网络;http、https都是建立在 NET 模块之上的;

    Buffer :缓冲,在Nodejs中处理二进制的数据,Buffer的存在是因为,javascript的字符串是以 utf-8 编码格式存储的,处理二进制的能力是很弱的,而网络层对于资源的存储请求等都是以二进制的格式交互的,所以 Nodejs 就有 Buffer 这个接口,来创建专门存放二进制数据的缓存区,并且提供给了一些方法对于这些数据进行进一步的处理;

    Buffer 在 Nodejs 中是可以直接访问的,不需要 require 来加载,Buffer 有一些静态方法,可以实例化,实例化之后的对象上有相应的属性和方法;

    生成实例的方法(1)new (2)传入一个size,以字节数为单位,传递给构造函数,生成一段内存区间;  (3)通过数组初始化;

    (1)通过new实例化  

      

    Buffer 是个对象,也是一个构造函数,具有自己的属性和静态方法;

    通过它new出来的实例,其实是V8引擎分配的一段内存;基本上是数组,成员都是整数值;

      

    Buffer对象与字符串相互转换过程是需要指定编码格式的,默认是 utf-8;

      

    (2)传入一个size,以字节数为单位,传递给构造函数,生成一段内存区间

        length属性表示缓存区的大小,写入内容超出长度的部分是不会被缓冲的,如下:

      

    (3)通过数组实例化,实例化后可以通过下标来访问某一个值;数组的一个某一项如果为小数,访问到的也只是整数

      

    - Buffer 实例的方法 - 

      

     - stream 流- 

        事件驱动,可控制;

      Readable 可读流  -- > 读取外部的数据,并吧读到的数据缓存到内部的 Buffer 数组中;

      Writable 可写流 -- > 负责消费数据,从可读流中获取数据,从获取到的 trunk 数据块进行处理;

      Duplex --

      Transform -- 转换流

      eg: 

      

      定制可读流、定制可写流、定制转换流,并且实现他们的内置接口;

      

      

      






  • 相关阅读:
    织梦开发——相关阅读likeart应用
    织梦标签教程
    织梦专题调用代码
    HIT 2543 Stone IV
    POJ 3680 Intervals
    HIT 2739 The Chinese Postman Problem
    POJ 1273 Drainage Ditches
    POJ 2455 Secret Milking Machine
    SPOJ 371 Boxes
    HIT 2715 Matrix3
  • 原文地址:https://www.cnblogs.com/wuhaoquan/p/9004428.html
Copyright © 2011-2022 走看看