From: Hans-Georg Michna on
I've had a strange effect today on an Ajax page, which pulls in
some data and displays it in the page, when the user clicks on a
link.

The trouble happens when the user clicks twice. The JavaScript
function is obviously started twice, and it calls the Ajax
function twice. Since I had no precautions against that in
place, the data got mixed up, and it gets rather unpleasant.

Now I use a property of the global function that is called by
the user's mouse click to construct a simple mutex (mutual
exclusion). The idea is that, if the property is false, the
function sets it to true and continues. If, however, it already
finds it true, it fires an alert to the user that the process is
already underway and that further clicks are futile, then
returns.

Trouble is, it does not work. When I click twice, the whole Ajax
process is still started twice. Only if I wait a few more
seconds, then click again, I get the alert.

Something strange is going on here. Any idea why this might
happen or how best to construct a simple, but reliable mutex for
Ajax purposes? I guess I don't really need an atomic operation,
as JavaScript is basically single-threaded. Or do I?

Of course it is still possible that I've merely made a stupid
mistake, but I will find that out tomorrow. The program, in
spite of its Ajax timing questions, may still cave in when it
smells the debugger. (:-)

Hans-Georg
From: Jorge on
On Jan 12, 11:58 pm, Hans-Georg Michna <hans-
georgNoEmailPle...(a)michna.com> wrote:
> I've had a strange effect today on an Ajax page, which pulls in
> some data and displays it in the page, when the user clicks on a
> link.
>
> The trouble happens when the user clicks twice. The JavaScript
> function is obviously started twice, and it calls the Ajax
> function twice. Since I had no precautions against that in
> place, the data got mixed up, and it gets rather unpleasant.
> (...)

I'd just null the onclick handler on entry and restore it upon
completion.
--
Jorge.
From: Hans-Georg Michna on
On Tue, 12 Jan 2010 18:00:51 -0800 (PST), Jorge wrote:

>On Jan 12, 11:58�pm, Hans-Georg Michna <hans-
>georgNoEmailPle...(a)michna.com> wrote:

>> I've had a strange effect today on an Ajax page, which pulls in
>> some data and displays it in the page, when the user clicks on a
>> link.
>>
>> The trouble happens when the user clicks twice. The JavaScript
>> function is obviously started twice, and it calls the Ajax
>> function twice. Since I had no precautions against that in
>> place, the data got mixed up, and it gets rather unpleasant.
>> (...)

>I'd just null the onclick handler on entry and restore it upon
>completion.

First of all, I did make a stupid mistake, meanwhile fixed, and
indeed JavaScript in its current incarnations doesn't need real
mutexes.

I did have to do something to prevent multiple activations
though, and I had already done it, but with that stupid mistake.
Now it works just fine.

I set a variable or property instead, because it feels more
atomic. Disabling and re-enabling the click handler has the
theoretical weakness that the second click might come in before
the handler is disabled. Who knows, perhaps some browsers have a
delay before or a layer above such DOM modifications.

Setting a variable is more atomic, so to say. It happens right
in the middle of JavaScript execution, touching nothing outside.
As long as JavaScript remains single-threaded, it is bound to be
absolutely reliable.

But I admit that these days changing the handler is very likely
to work just as well.

Hans-Georg
From: Scott Sauyet on
On Jan 13, 5:06 am, Hans-Georg Michna <hans-
georgNoEmailPle...(a)michna.com> wrote:
> I did have to do something to prevent multiple activations
> though, and I had already done it, but with that stupid mistake.
> Now it works just fine.
>
> I set a variable or property instead, because it feels more
> atomic.

Why not set that as a property of the function itself?

function myOneAtATimeFunc() {
if (arguments.callee.running) {
return;
}
arguments.callee.running = true;

// your processing here

// At end of function or in AJAX callback:
arguments.callee.running = false;
}

This keeps it out of larger scopes, but does what you need, I believe.

-- Scott
From: David Mark on
On Jan 12, 9:00 pm, Jorge <jo...(a)jorgechamorro.com> wrote:
> On Jan 12, 11:58 pm, Hans-Georg Michna <hans-
>
> georgNoEmailPle...(a)michna.com> wrote:
> > I've had a strange effect today on an Ajax page, which pulls in
> > some data and displays it in the page, when the user clicks on a
> > link.
>
> > The trouble happens when the user clicks twice. The JavaScript
> > function is obviously started twice, and it calls the Ajax
> > function twice. Since I had no precautions against that in
> > place, the data got mixed up, and it gets rather unpleasant.
> > (...)
>
> I'd just null the onclick handler on entry and restore it upon
> completion.

You would. :(