Hey,

2008/8/8  <[EMAIL PROTECTED]>:
> How to reproduce:
> Slot code has to delete something from DOM page (for example table from
> root) and then create something on it.
> You should activate slot reaction several times simultaneously (for
> example rapidly clicking the button that in connected to a slot many times).
> Sometimes the above error arises, and after that you have nothing to do
> besides reloading web-page (and application) as it won't work.
>
> Here's workaround that fixes this problem:
>
> Index: head/src/wt-2.1.5/src/web/skeleton/Wt.js
> ===================================================================
> --- head/src/wt-2.1.5/src/web/skeleton/Wt.js    (revision 776)
> +++ head/src/wt-2.1.5/src/web/skeleton/Wt.js    (revision 777)
> @@ -574,9 +574,12 @@
>  var randomSeed = new Date().getTime();
>
>  var update = function(self, signalName, e, feedback) {
> +  if(responsesPending)
> +    return;
> +
>   ${APP_CLASS}.private.autoJavaScript();
>   ++responsesPending;
> -
> +
>   if (${WT_CLASS}.isIEMobile) feedback = false;
>
>   if (quited) {
>
> I suppose that's not the correct one actually, but works as for me.
>

We have a longstanding discussions about what Wt should be doing for
these situations.

There are some options:

a) a simple, effective, solution would be to (always) ignore any event
while the previous response has not been received yet (like you
suggest). But the event is simply discarded, so the user will at least
be surprised.

b) to solve this, we could queue events until the previous response
has been received. This in fact, does not solve the problem, because
you could still have two clicks on a button that is supposed to
disappear after the first click.

c) we could complicate the API with a flag that allows the developer
to indicate whether subsequent events should be cancelled, but, this
would not be more work than:

d) give responsibility to the developer to make sure a button cannot
be clicked twice. He could that that by:

1) client-side: use WWidget::hide() or WWidget::disable()

 WPushButton *b = ...
 b->clicked.connect(SLOT(b, WWidget::hide));
 // or perhaps nicer: b->clicked.connect(SLOT(b, WWidget::disable));
 b->clicked.connect(SLOT(this, MyWidget::doStuff));

Because hide() and disable() are stateless slots, they are optimized
in client-side code that runs immediately when the button is clicked.
The server-side slot, doStuff() could then show() or enable() the
button again if he wishes.

2) server-side: delete the widget that originated the signal (and
perhaps recreate it).

 button_ = new WPushButton(...);
 button_->clicked.connect(SLOT(this, MyWidget::doStuff));

 void MyWidget::doStuff()
 {
   // do stuff...
   delete button_;
 }

This works because your application will process events one after the
other, and, the second event will no longer be valid ("exposed in Wt
talk") because the clicked Signal got deleted together with the
button.

All in all, I am in favor of option d). But, admittedly, this needs to
be documented somewhere! And, perhaps I am wrong about the
effectiveness of the two solutions?

Regards,
koen

-------------------------------------------------------------------------
This SF.Net email is sponsored by the Moblin Your Move Developer's challenge
Build the coolest Linux based applications with Moblin SDK & win great prizes
Grand prize is a trip for two to an Open Source event anywhere in the world
http://moblin-contest.org/redirect.php?banner_id=100&url=/
_______________________________________________
witty-interest mailing list
witty-interest@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/witty-interest

Reply via email to