javascript中同步和异步

  • js是一门单线程的语言,不像Java,类继承Thread再来个thread.start就可以开辟一个线程。js就像一条单一流水线,同一个时间只能做一个任务。

  • 同步和异步的差别在于这条流水线上各个流程的执行顺序不同

  • 最基础的异步是setTimeout和setInterval函数,很常见,但很少有人知道这就是异步。

  • <script type="text/javascript">
    	setTimeout(function(){
    		console.log("1")
    	},0);
    	console.log("2");
    </script>
    

    输出顺序是
    console输出结果

    任务队列,依次存放setTimeout中的function,在执行程序的时候,浏览器会默认setTimeout以及ajax请求这一类的方法都是耗时程序(尽管可能不耗时),将其加入一个队列中,该队列是一个存储耗时程序的队列,在所有不耗时程序执行过后,再来依次执行该队列中的程序。尽管setTimeout的time延迟时间为0,其中的function也会被放入一个队列中,等待下一个机会执行,当前不需要加入队列中的程序必须在队列的程序完成之前完成。

  • js是单线程,意味着所有的任务需要排队,等一个任务结束,才会执行后一个任务。如果前一个任务耗时很长,后一个任务就不得不一直等着。于是有了任务队列

    如果排队是因为计算量大,CPU忙不过来,倒也算了,但是很多时候CPU是闲着的,因为IO设备(输入输出设备)很慢(比如Ajax操作从网络读取数据),不得不等着结果出来,再往下执行。于是JavaScript语言的设计者意识到,这时主线程完全可以不管IO设备,**挂起处于等待中的任务,先运行排在后面的任务。**等到IO设备返回了结果,再回过头,把挂起的任务继续执行下去。

  • 所有任务可以分为两种

    • 同步任务(synchronous),指的是在主线程上排队执行的任务,只有前一个任务执行完毕,才能执行后一个任务

      • 如果在函数返回结果的时候,调用者能够拿到预期的结果(就是函数计算的结果),那么这个函数就是同步的。即使比较慢也会等他执行完。

        console.log('hello');

    • 异步任务(asynchronous),指的是不进入主线程,而进入任务队列(task queue)的任务,只有等主线程任务执行完毕,任务队列开始通知主线程,请求执行任务,该任务才会进入主线程执行

      • 在函数返回的时候,调用者还不能立即得到预期结果,而是将通过一定手段得到(例如回调函数),例如ajax操作。调用者不必主动等待,当被调用者得到结果之后会通过回调函数主动通知调用者。
  • 异步运行机制

    1. 所有的同步任务都在主线程上执行,形成一个执行栈(execution context stack)
    2. 主线程之外,还存在一个任务队列task queue。只要异步任务有了运行结果,就在任务队列之中放置一个事件。
    3. 一旦执行栈中的所有同步任务执行完毕,系统就会读取任务队列,看看里面有哪些事件,对应的异步任务结束等待状态进入执行栈开始执行。
    4. 主线程不断重复上面的第三步。
  • IO设备完成一项任务,就在任务队列中添加一个事件,表示相关的异步任务可以进入执行栈了,主线程读取任务队列,就是读取里面有哪些事件。

  • 任务队列中的事件,除了IO设备的事件以外,还包括一些用户产生的事件(比如鼠标点击、页面滚动等),比如 $(selectot).click(function),这些都是相对耗时的操作。只要指定过这些事件的回调函数,这些事件发生时就会进入任务队列,等待主线程读取。

  • 回调函数,就是那些会被主线程挂起来的代码,$(selectot).click(function)中的function就是一个回调函数。异步任务必须指定回调函数(callback),当主线程开始执行异步任务,就是执行对应的回调函数。例如ajax的success,complete,error也都指定了各自的回调函数,这些函数就会加入任务队列中等待执行。

  • js是单线程是因为浏览器在运行时只开一个js解释器,有两个线程操作DOM浏览器就晕了。浏览器不是单线程的,一些IO操作,定时器的计时和事件监听是由其他线程完成的。

©️2020 CSDN 皮肤主题: 书香水墨 设计师:CSDN官方博客 返回首页