美文网首页
异步和单线程 - 其他

异步和单线程 - 其他

作者: jrg陈咪咪sunny | 来源:发表于2017-12-07 17:54 被阅读0次

    单线程

    单线程执行顺序就是从上到下依次执行,同一时间内只能有一段代码被执行。
    虽然JavaScript是单线程的,可是浏览器内部不是单线程的。你的一些I/O操作、定时器的计时和事件监听(click, keydown…)等都是由浏览器提供的其他线程来完成的。

    如果想利用多线程处理一些耗时较长的任务,可以使用HTML5提出的Web Worker。

    一个js程序的单线程用来执行栈中的同步任务,当所有同步任务执行完毕后,栈被清空,然后读取任务队列中的一个待处理任务,并把相关回调函数压入栈中,单线程开始执行新的同步任务,执行完毕。

    单线程从任务队列中读取任务是不断循环的,每次栈被清空后,都会在任务队列中读取新的任务,如果没有新的任务,就会等待,直到有新的任务,这就叫任务循环。因为每个任务都由一个事件所触发,所以也叫事件循环。

    异步

    拿ajax来说,当页面的单线程执行xhr.send()之后,对于页面来说发送任务已经完成了。

    怎么发送,那是浏览器的事,和单线程无关;什么时候响应,这事说不准。

    为了及时地得到响应的内容,在单线程中注册相应的事件就好xhr.onreadystatechange = fn() {...}。注册之后,浏览器会在内部的其他线程中自动地帮我们监听该事件。直到该事件被触发,浏览器会在任务队列中添加一个任务等待该单线程执行。

    定时器

    setTimeout的作用是在间隔一定的时间后,将回调函数插入任务队列中,等栈中的同步任务都执行完毕后,再执行。因为栈中的同步任务也会耗时,所以间隔的时间一般会大于等于指定的时间。

    setTimeout(fn, 0)的意思是,将回调函数fn立刻插入任务队列,等待执行,而不是立即执行。看一个例子:

    setTimeout(function() {
    console.log("a")
    }, 0)
    for(let i=0; i<10000; i++) {}
    console.log("b")
    // 结果:b a
    

    打印结果表明回调函数并没有立刻执行,而是等待栈中的任务执行完毕后才执行的。栈中的任务执行多久,它就得等多久。

    ps: JavaScript单线程和其异步机制就如上所述。

    所谓的单线程并不孤单,它的背后有浏览器的其他线程为其服务,其异步也得靠其他线程来监听事件的响应,并将回调函数推入到任务队列等待执行。单线程所做的就是执行栈中的同步任务,执行完毕后,再从任务队列中取出一个事件(没有事件的话,就等待事件),然后开始执行栈中相关的同步任务,不断的这样循环。

    参考资料:* 并发模型与Event Loop

    相关文章

      网友评论

          本文标题:异步和单线程 - 其他

          本文链接:https://www.haomeiwen.com/subject/ecdjixtx.html