JavaScript既然是单线程的,那么异步要怎么理解?

不能理解异步到底说的是什么

阅读 15k
12 个回答

在这个回答的基础上,我总结了一下关于单线程、同步、异步、消息队列和事件循环等方面内容,写成了一篇文章:JavaScript:彻底理解同步、异步和事件循环(Event Loop)

原答案 >>>

看完我写的答案,如果题主你还不懂,那么你可以来打我:

所谓单线程,是指负责解释并执行JS代码的线程只有一个。我们不妨叫它主线程。

其实还有其他很多线程的,比如进行ajax请求的线程、监控用户事件的线程、定时器线程、读写文件的线程(例如在NodeJS中)等等。

同步和异步是怎么回事?以ajax请求为例:

异步就是:主线程执行到发送ajax请求的代码时,通知负责处理ajax请求的线程(不妨叫做ajax线程):“你给我发个请求吧,我把请求地址和参数都给你了”。然后主线程就不管这事儿了,继续执行后面的代码。等ajax线程收到HTTP响应的时候,就通知主线程:“你的响应来了,快来取吧”。主线程在合适的时候就会去取响应,进行适当的处理。

多说一句:ajax线程通知主线程的方式就是所谓的事件队列和事件循环机制

同步就是:主线程执行到发送ajax请求的代码时,它还是要通知ajax线程帮它发请求,但是它也停下来,啥都不干,等着接收响应。如果响应5秒后才拿到,那么他就等5秒。直到拿到响应后处理完了,才继续解释和执行接下来的代码。

所以,异步就是干某件事情(尤其是耗时的事情)的时候,不干等着,交给别人做,自己干其他事情,同时等通知。同步就是傻傻地等着。

现在你明白了,对于只有一个执行代码的线程的语言,如果没有异步是不行的。

因为是单线程的,就好像店里只有一位小姐,但是不能包夜。她先问你要什么服务,然后你想的过程(等待)。她会跑去问下一个客人,然后再回来看看你回答了没有。但是由于这个小姐非常灵活,跑得非常快,所以你感觉不到等待。可是,她就是不能包夜!

异步是一种代码执行方式,单线程下的异步可以这样理解,
假设有如下代码段,其中代码段B是需要异步执行的代码,
code block A;
async code block B;
code block C;
那么一个线程执行完A后,即将执行B,但发现B需要异步执行,那么线程将B放入队列中等待,然后跳过B,执行C,当C执行完后线程空闲,再去队列中把B取出来执行。

kfc中有一条队列,有三个人排队点餐, 第二个人没带钱,需要等人把钱送到他的手上,需要两个小时。

同步: 这个人会等两个小时排在队伍中并阻塞队列,这样第三个人也需要等待第二个拿到钱之后才能点餐。
异步: 第二个人先到新的地方等待,等到人把钱送到手中他才会重新排入队列中, 这样就不会影响第三个人点餐。

你可以参考这篇文章
JavaScript 运行机制详解:再谈Event Loop 标注版

你发送一个请求服务器总得响应吧,客户端等待响应需要一段时间,等服务器响应再有动作是同步,不需要等服务器响应就有动作的是异步

银行柜台办事,先取号,等叫号,差不多这个意思,

单线程:用javascript不能创建线程。
异步:调用一个函数,函数做的事情虽然不是立即能完成,但是函数立即返回。

新手上路,请多包涵

银行营业厅一个窗口按次序服务,一次叫一个号,这就是同步
但是如果某个人的资料少了,那对不起你把资料整理完了再来,业务员不会一直等你去整理资料,而是会直接
叫下一个号,并且让你准备好了再来取号。这个就叫做异步。整个办理过程不会因为你少了资料而耽搁,不会阻塞,如果服务员大家都歇了吧,这个人资料不齐大家等明天他整理完了资料再来(同步阻塞)那么营业厅肯定闹翻天了。

再来说多线程,就是开多个窗口。这个和同步异步没啥关系。

你可以认为有个全局的消息队列,需要异步执行的时候就把闭包push到里面去,当前的东西运行完就从里面pop出来一个执行。

有点类似gui编程里那个消息循环。比如你调用window.close,窗口不是马上关闭,而是把关闭的消息压进消息队列,当前回调执行完才会处理关闭这个消息。然后你觉得某个回调不卡是因为它很短,如果你在回调里面循环个几百万次,UI照样是卡住移动不了。

这个是不同于(其他语言的)server的,那些都是并发执行,带上下文切换的。主线程收到消息压入队列,然后子线程从队列里面取出来执行。

新手上路,请多包涵

其实异步很简单。
以一个js例子:
setTimeout(function(){
console.log('setTimeout');
},0)
console.log('1');
console.log('2');
console.log('3');
console.log('4');

//以上程序执行时,由于setTimeout异步函数的一种,所以执行时这个函数就交给另外一个线程处理,等1,2,3,4这些主线程执行完后,进行事件队列和事件循环机制判断另外一个线程执行完没,如果执行完则将其他线程的结果返回主线程!
所以看到的结果是1,2,3,4,setTimeout
类似这种异步的函数楼上已经也有说明啦!

可以适当理解一下CPU的时间片机制,单核处理器下,对每一个操作有一定的时间限制,以前单核CPU执行一个操作是28ms的限制,如果超过就重新入队,执行下一操作,这样就实现了单核心多线程。

撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进
推荐问题
宣传栏