node学习笔记(三)

来源:互联网 发布:org.w3c.dom.node 编辑:程序博客网 时间:2024/06/08 07:13

node之http

http协议是如何工作的:
1. http客户端发起请求,创建端口;
2. http服务器在端口监听客户端请求
3. http服务器向客户端返回状态和内容。

一个页面展示经历了什么?

  1. 域名解析;
  2. 查看有没有缓存DNS(浏览器自身的缓存和操作系统的自身的缓存)(chrome//net-internals/#dns);
  3. 读取本地host文件
  4. 浏览器发起DNS的一个系统调用
  5. 浏览器获得域名对应的IP地址后,发起HTTP经典的“三次”握手。

    1. A:你好,能听到我说话吗?
    2. B:听得到,听得到。
    3. A:开始聊天。
      拓展:断开连接时四次挥手:
      1. A:我不说了。
      2. B:等一下,我还没说完。
      3. B:好了,我说完了,我也不说了。
      4. A:好的,拜拜。
  6. TCP/IP连接建立起来后,浏览器就可以向服务器发送HTTP请求了,比如说用HTTP的GET方式请求一个根域里的一个域名,协议可以采用HTTP1.0的一个协议。

  7. 服务器端接收到了这个请求,根据路径参数,经过后端的一些 处理之后,把处理后的结果的数据(完整的HTML页面)返回给浏览器。

  8. 浏览器拿到完整的HTML页面代码之后,在解析和渲染这个页面的时候,里面的静态资源JS、CSS、图片、他们同样也是一个个HTTP请求,都需要经过上面的主要的七个步骤。

  9. 浏览器根据拿到的资源对页面进行渲染,最终把一个完整的页面呈现给用户。

写代码的过程中发现自己对很多概念的理解不是很准确,几个问题又出现在我的脑海:为什么这样写,node到底是什么,它的精髓在哪里?

总结过程中,发现以下几个概念的理解很重要
  1. 什么是回调?
    回调是异步编程最基本的方法,后续逻辑封装在回调函数中作为起始函数的参数 逐层去嵌套,通过这种方式让程序用我们所期望的方式走完流程。
  2. 什么是异步?
    程序的执行顺序和任务的排列顺序是不一致的,最基础的异步函数:setTimeout和setInterval
  3. 什么是阻塞I/O?
    input/output,程序执行过程中必然要进行很多I/O操作,读写文件、输入输出、请求响应等等。I/O操作时最费时的,至少相对于代码来说,在传统的编程模式中,举个例子,你要读一个文件,整个线程都暂停下来,等待文件读完后继续执行。换言之,I/O操作阻塞了代码的执行,极大地降低了程序的效率。
  4. 什么是非阻塞I/O?
    理解了阻塞I/O,那么非阻塞I/O就很好理解了。I/O操作不会阻塞程序的执行,也就是在I/O操作的同时,继续执行其他的代码(得益于node的事件循环机制)。
  5. 什么是事件驱动?
    当函数由于某个事件发生的时候而被调用执行的时候,这种函数调用的方式就叫做事件驱动。
  6. 什么是基于事件驱动的回调?
    我们注册的回调就是基于事件驱动的回调。
  7. 什么是事件循环(Event Loop)?
    如果有大量的异步操作,或者I/O耗时操作,以及定时器的延时操作,从而完成一些密集的任务,需要一个统一的机制来管理,这种机制就是事件循环。 (主线程从”任务队列”中读取事件,这个过程是循环不断的)。这个机制是什么样的呢:看了阮一峰老师的博客中关于Event Loop的一张图,醍醐灌顶:事件轮询的机制是,主线程 代码运行时会不断的产生堆和栈,而所有的异步回调函数会被压入栈中构成一个“回调队列”,当读取这个事件时,将调用与这个事件关联的JS函数代码,事件循环是先进先出的任务队列,整个任务队列是普通函数和回调函数构成的一个队列。

【以下内容摘自阮一峰老师博客】
但是,node中的运行机制如下,(与运行机制不同于浏览器)

(1)V8引擎解析JavaScript脚本。

(2)解析后的代码,调用Node API。

(3)libuv库负责Node API的执行。它将不同的任务分配给不同的线程,形成一个Event Loop(事件循环),以异步的方式将任务的执行结果返回给V8引擎。

(4)V8引擎再将结果返回给用户。

看了上面的概念之后,node的核心思想也不难理解:非阻塞,单线程,事件驱动。

异步之 回调函数方法 与 Promise对象方法 简单小实例

<!DOCTYPE html><html lang="en"><head>    <meta charset="UTF-8">    <title>Title</title>    <style>        .ball{            width: 40px;            height: 40px;            border-radius: 20px;        }        .ball1{            background-color: red;        }        .ball2{            background-color: green;        }        .ball3{            background-color: yellow;        }    </style></head><body><div class="ball ball1" style="margin-left: 0"></div><div class="ball ball2" style="margin-left: 0"></div><div class="ball ball3" style="margin-left: 0"></div>

回调函数

<script>    var ball1 = document.querySelector(".ball1");    var ball2 = document.querySelector(".ball2");    var ball3 = document.querySelector(".ball3");    function animate(ball,distance,callback) {            setTimeout(function () {                var marginLeft = parseInt(ball.style.marginLeft,10);                if(marginLeft === distance){                    callback();                }else {                    if(marginLeft < distance){                        marginLeft++;                    }else {                        marginLeft--;                    }                    ball.style.marginLeft = marginLeft + 'px';                    console.log(ball.style.marginLeft)                    animate(ball,distance,callback)                }            },13)    }    animate(ball1,100,function () {        animate(ball2,200,function () {            animate(ball3,300,function () {                animate(ball3,150,function () {                    animate(ball2,150,function () {                        animate(ball1,150,function () {                        })                    })                })            })        })    })</script>

Promise

<script>    var ball1 = document.querySelector(".ball1");    var ball2 = document.querySelector(".ball2");    var ball3 = document.querySelector(".ball3");    function promiseAnimate(ball,distance) {        return new Promise(function(resolve,reject) {            function ani() {                setTimeout(function () {                    var marginLeft = parseInt(ball.style.marginLeft,10);                    if(marginLeft === distance){                        resolve()                    }else {                        if(marginLeft < distance){                            marginLeft++;                        }else {                            marginLeft--;                        }                        ball.style.marginLeft = marginLeft + 'px';                        console.log(ball.style.marginLeft);                        ani()                    }                },10)            }            ani()        })    }    promiseAnimate(ball1,100)        .then(function () {            return  promiseAnimate(ball2,200)         })        .then(function () {            return  promiseAnimate(ball3,300)        })        .then(function () {            return  promiseAnimate(ball3,150)        })        .then(function () {            return  promiseAnimate(ball2,150)        })        .then(function () {            return  promiseAnimate(ball1,150)        })</script>