CodeSOD: Mutex.js |
Just last week, I was teaching a group of back-end developers how to use Angular to develop front ends. One question that came up, which did suprise me a bit, was how to deal with race conditions and concurrency in JavaScript.
Im glad they asked, because its a good question that never occurred to me. The JavaScript runtime, of course, is single-threaded. You might use Web Workers to get multiple threads, but they use an Actor model, so theres no shared state, and thus no need for any sort of locking.
Chris Rs team did have a need for locking. Specifically, their .NET backend needed to run a long-ish bulk operation against their SqlServer. It would be triggered by an HTTP request from the client-side, AJAX-style, but only one user should be able to run it at a time.
Someone, for some reason, decided that they would implement this lock in front-end JavaScript, since thats where the AJAX calls were coming from..
var myMutex = true; //global (as in page wide, global) variable
function onClickHandler(element) {
if (myMutex == true) {
myMutex = false;
// snip...
if ($(element).hasClass("addButton") == true) {
$(element).removeClass("addButton").addClass("removeButton");
// snip...
$.get(url).done(function (r) {
// snip... this code is almost identical to the branch below
setTimeout("myMutex = true;", 100);
});
} else {
if ($(element).hasClass("removeButton") == true) {
$(element).removeClass("removeButton").addClass("addButton");
// snip...
$.get(url).done(function (r) {
// snip... this code is almost identical to the branch above
setTimeout("myMutex = true;", 100);
});
}
}
}
}
You may be shocked to learn that this solution didnt work, and the developer responsible never actually tested it with multiple users. Obviously, a client side variable isnt going to work as a back-end lock. Honestly, Im not certain thats the worst thing about this code.
First, they reinvented the mutex badly. They seem to be using CSS classes to hold application state. They have (in the snipped code) duplicate branches of code that vary only by a handful of flags. They arent handling errors on the request- which, when this code started failing, made it that much harder to figure out why.
But its the setTimeout("myMutex = true;", 100); that really gets me. Why? Why the 100ms lag? What purpose does that serve?
Chris threw this code away and put a mutex in the backend service.
| Комментировать | « Пред. запись — К дневнику — След. запись » | Страницы: [1] [Новые] |