zoukankan      html  css  js  c++  java
  • JavaScript单线程和异步机制

    说到这个异步,首先就要弄懂,什么是同步?我们先来看看,同步和异步的区别在什么地方。 
    先来看看一个列子

    console.log(100)
    setTimeout(function(){
      console.log(200)
    },1000)
    console.log(300)

    打印出来的顺序,100 300 200 
    这样子应该看明白了,这个程序是没有阻塞的.. 
    一步一步往下执行,先打印出100,然后是是一个setTimeout事件,一秒钟之后打印出200.然后再打印出300.可以函数实际却不是这么执行的。 
    这就是一个异步的操作。setTimeout是一个异步的事件。我们来对比看看同步的

    console.log(100)
    alert(200)
    console.log(300)

    这就是一个同步的执行过程,首先打印出的100,然后就是弹出一个alert框,你要是一生都不点击确认框,那么这个300就永远也打印不出来。很明显,这就是一个阻塞的过程了 
    既然有了异步,那么这种异步的实际应用场合是什么样子的呢? 
    一句话,如果不想阻塞后面的操作,那就来一个异步吧。 
    主要场景如下 
    定时任务:setTimeout setInterval 
    网络请求:ajax操作,动态img请求 
    事件处理:click等事件 
    定时任务本文的一开始就介绍过了,万一是n秒之后呢,难道我要等着你么?想得美! 
    看看ajax的网络请求

    console.log(100)
    $.get('../data.json',function(){
      console.log(200)
    })
    console.log(300)

    这个网络请求,完全是要看网络怎么样,万一请求到了一万年之后,那怎么办?所以咯,我要异步异步异步!!!

    console.log(100)
    var img=document.createElement('img')
    img.onload=function(){
    console.log(200)
    img.src="../hahhahah.jpg"
    }
    console.log(200)

    这个也是同理的,要是你的图片一直加载不出来,那不好意思,你继续,我先往下进行

    console.log(100)
    document.getElementById('haha').addEventListener('clcik',function(){
    console.log("终于点击了")
    })
    console.log(200)

    鬼知道你什么时候要触发这个点击事件,所以咯,还是一样的哈,啥时候点击了,啥时候执行你。不要影响到别人

    难道就没人好奇么?为什么这个js要采取这样子的异步的模式 

    这就要说到单线程了,单线程!!!!!!!!!!!!

    console.log(100)
    setTimeout(function(){
      console.log(200)
    })
    console.log(300)

    先打印出100,然后呢?看到了setTimeout这个函数,哎呀妈呀,这个可是一个异步操作呀,关进小黑屋,先一边呆着去。继续执行,打印出300.好了,程序执行完了,去看看那个黑屋里面的货怎么样了,打印出200

     什么是单线程?意思就是说,一次只能干一个事,就像我们人一样,你能一边学习,一边做饭吗?是同时同步,而不是,我上一秒学习,下一秒做饭,你这个是快速的上下文切换 
    还有一种情况,你一边听歌,一边做饭,那好吧,这个谁不会呢?我们这里指的是,你自己有意识的,需要付出心思的同时干两种事情 
    程序是单线程的,只能挨个的执行,这个没执行完,下一个免谈,要是碰见了耗时长的任务,如果是多线程的话,还能用另外一个线程来执行,但是单线程的情况下,那你就只能自认倒霉,你就这么耗着吧。 
    当然了,人类是聪明的,单线程的春天到了。因为我们想到了异步呀,你不是耗时很长会阻塞么,那你滚吧

    那好,我滚了,但是我还是要执行的啊,那我什么时候执行呢? 
    这个时候,就要回调来处理 
    啥叫回调? 
    我的理解就是,你要在某个函数之后调用,不能抢了人家的顺序

    function a(){
      console.log("a")
    }
    function b(fn){
      console.log("b")
      fn()
    }
    b(a)

    像上面的这个函数,是不是我先调用了函数b,然后函数a才能执行啊,那你可以反驳,这样子好麻烦,我直接按顺序不也可以吗。看代码

    function b(){
      console.log("b")
    }
    function a(){
      console.log("a")
    }
    b()
    a()

    这样子不也是,先调用了函数b,然后再调用了函数a么?所以,这说明。回调函数真正的用处不在这儿,因为这两种写法没啥子大不了的区别

    console.log(100)
    setTimeout(function(){
      console.log(200)
    },1000)
    console.log(300)

    那这个例子呢?setTimeout函数被关去了小黑屋,现在轮到他调用了,一秒之后,打印出了200。这就是回调函数的作用啊,100 200都打印出来了之后,又再过了一秒,才轮到这个函数执行,打印出了200

    console.log(100)
    $.get('../data.json',function(data){
      console.log(data)
    })
    console.log(300)

    看这个网络请求。100 300都打印出来了之后,我去处理这个ajax的请求,请求完了。获取到数据了,我总不能不管了吧,获取的数据总要取出来吧,这个时候,我定义了一个函数,就是用来当请求处理完了之后,用来处理后续的操作的,比如取得请求数据啥的。 
    总结:js是一个单线程的,要是遇见耗时的操作,不能白白就这么耗着啊,让这个操作先一边玩去,等我处理完了之后,再去处理这个耗时的操作,当我操作成功之后,用一个回调函数来去处理,至于什么时候请求完成,那就是别的知识点了。这个回调函数具体啥时候执行,就要看你具体是什么操作了

  • 相关阅读:
    Python sys.argv用法详解及应用
    Python map() 函数
    Python中enumerate用法详解
    闭包,作用域链,垃圾回收,内存泄露
    jQuery 常用代码集锦
    关于作用域和作用域链最完整的简述
    git 合并commit
    apollo-client
    关于对称加密和解密
    接口校验机制
  • 原文地址:https://www.cnblogs.com/yiyistar/p/6683180.html
Copyright © 2011-2022 走看看