Yogesh Patel
Yogesh Patel

Reputation: 105

Javascript / dojo - how to prevent async calls issue? RACE condition due to dojo widget calls

We have a web portal, when user submits a form, after filling all mandatory details, the UI is posting null / empty value for one of the mandatory field – “Name” to the server API.

Name is a textbox (a dojo widget), it has onFocusOut() method handled. This method performs some checks / serialization / de-serialization and asynchronously updates Name property of main object say "employee".

There is a submit() method, that is triggered on click of Submit button on this form. This method posts employee object as payload to server API.

ISSUE:

When user types in the name textbox, and without loosing focus clicks on Submit button. This triggers two async methods (onFocusOut() and submit() methods) separated by just a fraction of milli second.

In some rare scenarios, submit() is posting the employee object to server API, before the Name property of employee object is updated by onFocusOut() method.

SOLUTION?

Here are different possible solution to this issue –

What is the optimum solution for such RACE condition? What are the best practices to handle such situation in dojo application?

Upvotes: 1

Views: 194

Answers (2)

Daniel Ursu
Daniel Ursu

Reputation: 459

Setting intermediateChanges: true on your inputs should fix these issues. https://davidwalsh.name/dijit-intermediatechanges

Upvotes: 0

Michel Engelen
Michel Engelen

Reputation: 573

Race conditions are some of the hardest things to fix in JavaScript, so this is a good question. Your provided solutions for this do point in the right direction, so let me take on three of them and see if I can be of any help with this.

1. Using setTimeout() to delay the submit() call

This is definitely one option to prevent such a situation, but there are some caveats to it.

What happens when you wrap your submit() in setTimeout() (or rather use it as a callback in the setTimeout()) is that the submission gets stacked onto the event queue.

This way the submit() will surely get delayed, but it can eventually slow down your code by a fair margin depending on other function calls that get stacked before your submit().

I don't know if you are familiar with how JavaScript handles function calls and events, but there are some very helpful ressources about this topic to be found online. Here is a talk from Phil Roberts about it that helped me understand it a lot better: What the heck si the event loop anyway?

2. Use the onChange() event instead of onFocusOut()

In my opinion this is by far the better option for your problem.

In React this method is used to create so called controlled components. With every change to the input a function gets called which updates the state with the new value. This new value is then used to rerender the component (which is very efficient in React due to the way it detects changes in the DOM).

There is a good explanation to be found here on SO: controlled VS uncontrolled components

Since you are using some kind of model/object to store the values this could be your best shot.

3. Using a validation function before sending the data

Well, this could be a good solution as well, especially when you design your function as a Promise, but there are some things to consider before taking this approach.

At first you do would need some kind of model to check if every input taken is correct and meets the expectation. This can be very unsafe regarding the users intention and can lead to unsatisfied user experiences.

And secondly there is the problem that you need to take one more step to successfully post the data to the API, which always holds the chance to produce a bug/several bugs in your code.


TL:DR; I would go with option 2 since it is the safest among your solutions.

I hope I could be of help with this. :D

Upvotes: 1

Related Questions