天天看点

05慕课网《进击Node.js基础(一)》HTTP概念进阶(同步/异步)

HTTP模块介绍

支持http协议的更多特性

不缓存请求和响应

API比较底层处理流相关,信息解析

HTTP相关概念

回调

将函数作为参数传到执行函数中,参数函数在执行函数中嵌套执行

function learn(something){
    console.log(something);
}

function we(callback,something){
    something+=' is cool'
    callback(something)
}
//具名函数
we(learn,'Nodejs')
//匿名函数
we(function(something){
    console.log(something)
},'hello')      

同步/异步

JavaScript中的异步函数

//在指定间隔内执行一次
setTimeout(function(){
   alert('1')
},2000)      
//在执行间隔内重复执行,但是需要关闭alert,不会弹出N个
setInterval(function(){
   alert('1')
},2000)      

同步

任务顺序执行,等待上一个执行完成再执行下一个

//同步
var c=0
function print(){
    console.log(c)
}

function plus(){
    setTimeout(function(){
        console.log('aaa')
    },1000)
    c+=1;
}
plus()
print()      
05慕课网《进击Node.js基础(一)》HTTP概念进阶(同步/异步)

异步

setTimeout()不只是是一个异步函数,它还涉及到了计时器线程

多个setTimeout()函数首先按照先后顺序压入异步函数队列中

主程序执行完毕后开始执行异步函数队列

异步队列中若是setTimeout函数,则放到计时器线程中

在计时器线程中,如果时间相等,则按进入线程的先后顺序执行

若有A,B线程,A正在执行,但是B已经到了该执行的时间,那么B不会执行,直到等待A执行完毕才会执行

若异步队列中有需要立即执行的函数,那么久首先执行,A会等待,一次只执行一个

或者是setTimeout()函数首先放到计时器线程当中,等到指定的时间放入执行队列当中

每个任务都有多个回调函数,前一个任务执行完毕后不执行下一个任务,而是执行回调函数;后一个任务按照任务的排列顺序执行,不会等待上一个任务执行完毕

//异步,任务执行完成后执行回调函数
var c=0
function print(){
    console.log(c)
}

function plus(callback){
    setTimeout(function(){
        c+=1;
        callback()
    },1000)
    console.log('a')
}
plus(print)      
05慕课网《进击Node.js基础(一)》HTTP概念进阶(同步/异步)

有关异步的一个问题:https://www.jianshu.com/p/e5225ba4a025

参考闭包:http://www.jb51.net/article/24101.htm

//以下代码的输出是什么?如何修改
for (var i = 1; i <= 5; i++) {
    setTimeout( function(){  //function timer()可以是具名函数
        console.log(i);
    },i*1000);
}
//输出5个6:6 6 6 6 6 6
//因为setTimeou函数是异步的,在正文执行完后,i=6的时候开始执行,而且是执行5次,所以打印5个6      

错误答案:

for (var i = 1; i <= 5; i++) {
    setTimeout( function(i){  //function timer()可以是具名函数
        console.log(i);
    },i*1000);
}

//输出5 个 undefined;调用匿名函数,没有传值,i引用的是参数i的值,i为undefined      

正确答案一:

for (var i = 1; i <= 5; i++) {
    (function() {
        var j = i;
        setTimeout( function() {
            console.log(j);
        },i*1000 ); //这一行将i*1000改为j*1000也行,并不影响
    })();
}
//此处用了立即执行函数(function(){})();使setTimeout中函数形成了闭包
//什么是闭包:当内部函数(setTimeout中的匿名函数) 在定义它的作用域(立即执行函数) 的外部(立即执行函数外部) 被引用时(异步,最后调用,在外部调用)
//      就创建了该内部函数(匿名函数)的闭包 
//      如果内部函数(匿名函数)引用了位于外部函数的变量,当外部函数调用完毕后,这些变量在内存不会被 释放,因为闭包需要它们.

//根据闭包的定义,我们面对这个问题的思路:
// 匿名函数function(){ console.log(j) }外要再套一层立即执行函数
// j为引用立即执行函数中的变量
// 通过异步调用匿名函数      

正确答案二:使用let块级作用域形成闭包,不太了解就不说了

for (var i = 1; i <= 5; i++) {
    let j = i;
    setTimeout(function timer() {
        console.log(j);
    },j*1000);
}      
归纳一下就是:函数里面有函数,函数外面调用里面函数;但是函数外面怎么调用函数里面的函数呢?
1.使用异步,异步是最后执行;上面的例子是这样
2.该函数的结果为里面的函数,先var fn=该函数,然后执行fn,这样就形成了闭包      

I/O

磁盘上数据读写

单线程/多线程

一次只能进行一个请求和响应

多个请求和响应同时进行

阻塞/非阻塞

阻塞:客户端一直等待服务端响应

非阻塞:请求无响应就去干别的,过段时间再请求

事件

点击,移动等操作

事件驱动

函数在事件发生的时候执行

基于事件驱动的回调

函数中的回调函数

事件循环

密集任务异步执行放到loop队列,单线程不断查询loop队列