所有的JavaScript事件处理程序的脚本是由一个主事件队列处理。这意味着事件处理程序一次运行一个事件处理程序,一个事件处理程序一直运行直至完成,然后才能开始运行。因此,在Javascript中没有任何典型的竞争条件,人们会以多线程语言看到多线程语言可以同时运行(或时间片)并冲突以访问变量。 JavaScript中的任何单个执行线程都将在下一个启动之前完成。这就是Javascript的工作原理。事件从事件队列中拉出,代码开始运行以处理该事件。该代码自行运行,直到它将控制权返回给系统,然后系统将从事件队列中拉出下一个事件并运行该代码,直到它将控制权返回给系统。
因此,由两个执行线程同时执行的典型竞态条件不会在Javascript中发生。
这包括所有形式的JavaScript事件,包括:用户事件(鼠标,按键等),计时器事件,网络事件(AJAX回调),等等
你其实可以做的唯一的地方Javascript中的多线程与HTML5 Web Workers是一样的,但它们与常规javascript非常分离(它们只能通过消息传递与常规JavaScript进行通信),并且根本无法操作DOM,并且必须拥有自己的脚本和命名空间等。
虽然我不会在技术上将这称为竞争条件,但有情况因为它的一些异步操作可能导致两个或多个异步操作在运行,并且在每个操作相对于其他操作完成时可能是不可预知的。这会产生时间上的不确定性(如果操作的相对时间对您的代码很重要)会创建一些您必须手动编写的内容。您可能需要对操作进行排序,以便运行,并且在开始下一个操作之前,您可以等待它完成。或者,你可以开始所有的三个操作,然后有一些代码收集所有三个结果,当他们都准备好了,然后你的代码继续。
在现代的Javascript中,承诺通常用于管理这些类型的异步操作。
所以,如果你有三个异步操作,每个返回一个承诺(如从数据库中读取,获取来自其他服务器的请求,等...),你可以手动序列,然后将这样的:
a().then(b).then(c).then(result => {
// result here
}).catch(err => {
// error here
});
或者,如果你想他们都(所有在飞行的同时)一起运行,只是知道,当他们都做了,你可以这样做:
Promise.all([a(), b(), c()])..then(results => {
// results here
}).catch(err => {
// error here
});
虽然我不会把这些竞态条件,他们在设计你的代码来控制inde的同一个大家族里终止排序。
在浏览器的某些情况下可能会出现一种特殊情况。这不是一个真正的竞争条件,但是如果你在临时状态下使用大量的全局变量,可能需要注意。当你自己的代码导致另一个事件发生时,浏览器有时会同步调用该事件处理程序,而不是等到当前的执行线程完成。这方面的一个例子是:
- 点击
- 单击事件处理程序的变化集中到其他领域
- 其他领域具有的onfocus事件处理程序
- 浏览器调用立即onfocus事件处理程序
- onfocus事件处理程序运行
- 其余的click事件处理程序运行(在.focus()调用之后)
这在技术上不是竞争条件,因为在onfocus事件处理程序将执行时(在调用.focus()
期间),它是100%已知的。但是,它可以创建一个事件处理程序运行而另一个处于执行中的情况。
为什么不只是让flash调用javascript函数呢? – zellio