Javascript/dojo-如何防止异步调用问题?dojo小部件调用导致的竞争条件

Javascript/dojo-如何防止异步调用问题?dojo小部件调用导致的竞争条件,javascript,architecture,dojo,race-condition,Javascript,Architecture,Dojo,Race Condition,我们有一个web门户,当用户提交表单时,在填写所有必需的详细信息后,UI会将其中一个必填字段“Name”的空/空值发布到服务器API Name是一个文本框(一个dojo小部件),它处理了onFocusOut()方法。此方法执行一些检查/序列化/反序列化,并异步更新主对象的Name属性,例如“employee” 有一个submit()方法,单击此表单上的提交按钮会触发该方法。此方法将employee对象作为有效负载发布到服务器API 问题: 当用户在名称文本框中键入时,在不失去焦点的情况下单击提交

我们有一个web门户,当用户提交表单时,在填写所有必需的详细信息后,UI会将其中一个必填字段“Name”的空/空值发布到服务器API

Name是一个文本框(一个dojo小部件),它处理了
onFocusOut()
方法。此方法执行一些检查/序列化/反序列化,并异步更新主对象的Name属性,例如“employee”

有一个
submit()
方法,单击此表单上的提交按钮会触发该方法。此方法将employee对象作为有效负载发布到服务器API

问题:

当用户在名称文本框中键入时,在不失去焦点的情况下单击提交按钮。 这将触发两个异步方法(
onFocusOut()
submit()
方法),它们之间的间隔仅为几分之一毫秒

在一些罕见的情况下,
submit()
在员工对象的Name属性被
onFocusOut()更新之前,将员工对象发布到服务器API。

解决方案

以下是该问题的不同可能解决方案——

  • 使用
    setTimeout()
    延迟触发
    submit()
    方法
  • 使用文本框的
    onChange()
    而不是
    onFocusOut()
    更新模型
  • submit()
    方法API post之前立即进行函数调用以检查所有验证
  • 使用类级别标志。在
    onFocusOut()方法的开始和结束时将其设置为开/关。Submit等待设置此标志,然后执行API post

对于这种竞争条件,什么是最佳解决方案?在dojo应用程序中处理这种情况的最佳实践是什么?

竞争条件是
JavaScript
中最难解决的问题,因此这是一个好问题。您为此提供的解决方案确实指向了正确的方向,所以让我来介绍其中的三个,看看我是否能在这方面提供帮助

1。使用
setTimeout()
延迟
submit()
调用

这绝对是防止这种情况的一种选择,但也有一些注意事项

当您将
submit()
包装在
setTimeout()
中(或者更确切地说,将其用作
setTimeout()
中的
回调
)时,会发生的情况是提交被堆叠到
事件队列中

这样一来,
submit()
肯定会延迟,但它最终会使代码的速度降低相当大的幅度,这取决于在
submit()
之前堆积的其他函数调用

我不知道您是否熟悉
JavaScript
如何处理函数调用和事件,但是可以在网上找到一些关于这个主题的非常有用的资源。以下是Phil Roberts关于它的谈话,它帮助我更好地理解它:

2。使用
onChange()
事件代替
onFocusOut()

在我看来,这是解决你问题的更好的选择

React
中,此方法用于创建所谓的
受控组件
。对
输入的每次更改
都会调用一个函数,用新值更新
状态
。然后使用此新值重新加载组件(由于它检测
DOM
中的更改,因此在
React
中非常有效)

这里有一个很好的解释:

由于您使用某种模型/对象来存储值,因此这可能是您的最佳选择

3。发送数据前使用验证功能

<>这可能是一个很好的解决方案,尤其是当你把你的函数设计成Engult时,但是在采用这种方法之前还有一些事情要考虑。 首先,您需要某种模型来检查每个输入是否正确,是否符合预期。这对于用户的意图来说是非常不安全的,并可能导致用户体验不满意

第二个问题是,您需要再采取一个步骤来成功地将数据发布到
API
,它总是有机会在代码中产生一个或多个bug


TL:DR; 我会选择选项2,因为它是您的解决方案中最安全的


我希望我能在这方面有所帮助D

在输入上设置
中间更改:true
,应该可以解决这些问题。

请向我们提供显示此行为的代码。。。当我们能真正看到这里发生的事情时,帮助你会更容易。@MichelEngelen,由于保密条款,我不能发布代码。好的,我会尽量回答你的问题,没有示例代码