不能理解异步到底说的是什么
因为是单线程的,就好像店里只有一位小姐,但是不能包夜。她先问你要什么服务,然后你想的过程(等待)。她会跑去问下一个客人,然后再回来看看你回答了没有。但是由于这个小姐非常灵活,跑得非常快,所以你感觉不到等待。可是,她就是不能包夜!
异步是一种代码执行方式,单线程下的异步可以这样理解,
假设有如下代码段,其中代码段B是需要异步执行的代码,
code block A;
async code block B;
code block C;
那么一个线程执行完A后,即将执行B,但发现B需要异步执行,那么线程将B放入队列中等待,然后跳过B,执行C,当C执行完后线程空闲,再去队列中把B取出来执行。
kfc中有一条队列,有三个人排队点餐, 第二个人没带钱,需要等人把钱送到他的手上,需要两个小时。
同步: 这个人会等两个小时排在队伍中并阻塞队列,这样第三个人也需要等待第二个拿到钱之后才能点餐。
异步: 第二个人先到新的地方等待,等到人把钱送到手中他才会重新排入队列中, 这样就不会影响第三个人点餐。
你可以参考这篇文章
JavaScript 运行机制详解:再谈Event Loop 标注版
银行营业厅一个窗口按次序服务,一次叫一个号,这就是同步
但是如果某个人的资料少了,那对不起你把资料整理完了再来,业务员不会一直等你去整理资料,而是会直接
叫下一个号,并且让你准备好了再来取号。这个就叫做异步。整个办理过程不会因为你少了资料而耽搁,不会阻塞,如果服务员大家都歇了吧,这个人资料不齐大家等明天他整理完了资料再来(同步阻塞)那么营业厅肯定闹翻天了。
再来说多线程,就是开多个窗口。这个和同步异步没啥关系。
你可以认为有个全局的消息队列,需要异步执行的时候就把闭包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
类似这种异步的函数楼上已经也有说明啦!
27 回答13k 阅读
8 回答3.5k 阅读✓ 已解决
6 回答1.3k 阅读✓ 已解决
5 回答5.3k 阅读✓ 已解决
4 回答1.6k 阅读✓ 已解决
3 回答1.7k 阅读
4 回答2.3k 阅读✓ 已解决
在这个回答的基础上,我总结了一下关于单线程、同步、异步、消息队列和事件循环等方面内容,写成了一篇文章:JavaScript:彻底理解同步、异步和事件循环(Event Loop)
原答案 >>>
看完我写的答案,如果题主你还不懂,那么你可以来打我:
所谓单线程,是指负责解释并执行JS代码的线程只有一个。我们不妨叫它主线程。
其实还有其他很多线程的,比如进行ajax请求的线程、监控用户事件的线程、定时器线程、读写文件的线程(例如在NodeJS中)等等。
同步和异步是怎么回事?以ajax请求为例:
异步
就是:主线程执行到发送ajax请求的代码时,通知负责处理ajax请求的线程(不妨叫做ajax线程):“你给我发个请求吧,我把请求地址和参数都给你了”。然后主线程就不管这事儿了,继续执行后面的代码。等ajax线程收到HTTP响应的时候,就通知主线程:“你的响应来了,快来取吧”。主线程在合适的时候就会去取响应,进行适当的处理。多说一句:ajax线程通知主线程的方式就是所谓的事件队列和事件循环机制。
同步
就是:主线程执行到发送ajax请求的代码时,它还是要通知ajax线程帮它发请求,但是它也停下来,啥都不干,等着接收响应。如果响应5秒后才拿到,那么他就等5秒。直到拿到响应后处理完了,才继续解释和执行接下来的代码。所以,异步就是干某件事情(尤其是耗时的事情)的时候,不干等着,交给别人做,自己干其他事情,同时等通知。同步就是傻傻地等着。
现在你明白了,对于只有一个执行代码的线程的语言,如果没有异步是不行的。