JavaScript中按钮点击回调与等待的Promise之间是否可能存在竞态条件?
JavaScript中按钮点击回调与等待的Promise之间是否可能存在竞态条件?
问题场景
我有一个HTML设置页面和对应的JavaScript文件,页面展示了从后端获取的可修改配置项,底部有一个Apply按钮。具体交互逻辑如下:
- 用户点击
Apply时,$("#settings").submit(...)回调会触发,弹出一个带提示信息和OK按钮的模态框,用户可通过点击右上角X或OK关闭模态框。 - 点击
OK按钮时,$("#OK-btn").on("click"...(标记为(a))这个回调会把默认值为false的布尔变量apply_changes设为true。 - 同时,在
$("#settings").submit(...)的逻辑中,弹出模态框后会创建一个new Promise((resolve) => ...,里面给模态框绑定了modal.addEventListener("click"...(标记为(b)),用来检查apply_changes的值。
我的疑问是:用户点击模态框的OK后,设置变量的回调(a)和Promise里检查变量的回调(b)之间会不会出现竞态条件?目前测试还没遇到,但想知道底层的执行逻辑。
对应的流程示意图:
$("#settings").submit()... <displays> ---> Modal OK ---> $("#OK-btn").on("click"... (a) set apply_changes | ^ <creates> | | | V | new Promise((resolve) => eventListener("click")---- (b) test apply_changes
结论与解释
根据社区用户@Bergi的提示,这种情况不会出现竞态条件——关键原因在于事件的冒泡机制:当用户点击OK按钮时,事件会先从按钮元素本身向上冒泡到模态框元素。也就是说,绑定在OK按钮上的回调(a)会先执行,把apply_changes设为true,之后事件才会冒泡到模态框,触发绑定在它上面的回调(b),这时候检查到的变量值已经是更新后的了,不会出现时序混乱的问题。
优化后的实现
按照这个思路,我也重构了原本的代码,去掉了容易引发疑惑的布尔变量apply_changes,不再用额外的回调来设置它。现在直接在模态框的点击监听器里,通过$(document.activeElement).is()来判断事件到底是从哪个元素触发的,以此来决定后续的操作逻辑,代码结构更简洁清晰。
备注:内容来源于stack exchange,提问作者Dodomac
相关产品推荐
相关产品推荐

