如果你的程序中只有一个事件循环,没有其他代码,那么是否有可能在同一时间运行两行代码?
不可能。
一个事件循环中的所有代码都在一个操作系统线程中运行,所以任何时刻只能有一段代码在运行。
在一个有事件循环的程序中,是否可以有其他线程?
是的。
例如,在 node.js
中,所有的 Javascript 代码都在一个线程中运行,但还有其他工作线程来处理网络请求和其他 I/O。
在一个事件循环中,是否由操作系统来负责调度函数执行的顺序?
不是。
例如,用Python的 asyncio
,做调度的代码是一个 Python 程序。
事件循环真的是一个循环吗?(就像像 for
循环或 while
循环?)
是的。
通常事件循环都是以while
循环的形式实现的,它看起来像这样。
1 | while True: |
(以上是 Python 的 asyncio
事件循环的实际代码)
事件循环如何决定下一个函数的运行?
通过队列。
当函数准备好运行时,它们会被推到队列中,然后事件循环按顺序执行队列中的函数。
如果一个网络请求返回,并且它有一个附加的回调,该回调是否会被推送到事件循环的队列中?
是的。
当网络请求或其他 I/O 完成后,或者用户点击了某些东西,或者因为该函数计划在那时运行等,函数可能会被推入事件循环的队列中。
常规函数和异步函数一样吗?
不一样。
异步函数特殊之处在于,它们可以被“暂停”并在稍后的事件循环中重新启动。
例如,在下边这段 Javascript 代码中
1 | async function panda() { |
事件循环调度 elephant()
,暂停 panda
,并在 elephant()
运行完毕后调度 panda()
重新启动。普通的非 async
函数不能像这样暂停和重启。这些可以暂停和重启的异步函数的另一个名字是协程。
如果你要求事件循环在某个时间运行一个函数(比如 Javascript 中的setTimeout
),它能保证在那个时间运行吗?
不能。
事件循环会尽力而为,但有时会延迟。
在 Javascript 中,promises、setTimeout、async/await 和回调是否都使用相同的事件循环?
是的。
虽然它们的语法不同,但它们是安排代码稍后运行的不同方式。
在下边这段代码中,是否可以让事件循环在x=3后中断,然后运行别的东西?
1 | x = 3; |
不能。
你需要显式让步给事件循环,让它运行一个不同的函数,例如使用 await
如果你运行一些CPU密集型的代码,如下,事件循环最终会中断代码吗?
1 | while(true) { |
不会。
通常,你可以通过运行一些 CPU 密集型操作来长时间阻塞事件循环。
如果你的Web 服务器事件循环中 CPU 的使用率到达100%,当新的 HTTP 请求进来时,是否能够立即响应?
不能。
如果你的事件循环的 CPU 总是很忙,那么新进来的事件就不会得到及时处理。
Javascript代码总是有一个事件循环吗?
是的。
至少在 node.js
和浏览器中是这样的,Javascript 代码总是有一个事件循环运行。
是否存在一个所有的事件循环都在使用标准的事件循环库?
没有。
在不同的编程语言中,有很多不同的事件循环实现。
你可以在任何编程语言中使用事件循环吗?
可以。
大多数编程语言并没有像 Javascript 那样的“一切都在事件循环中运行”的模式,但许多语言都有事件循环库。而且从理论上讲,即使还没有自己语言的事件循环库,你也可以编写一个。