1

I have a jQuery widget, which contains a variable this.options._offset and a function _drawPlot(). When user drag & drop, a function _drawPlot() will be executed and this.options._offset will be updated at the end.

Now the problem is, a user may drag & drop too fast, making the variable _offset not consistent. For example, two drag & drop operations A and B, the execution sequence maybe:

A: plotting
A: update offset
B: plotting
B: update offset

Or:

A: plotting
B: plotting
A: update offset
B: update offset

The value offset is not correct for second case. I thought JS is single threaded and never expected this to happen. It is like semaphore in OS. Or it is just because console.log is cheating me? But anyway, the function _drawPlot(), which makes use of _offset, behaves wrongly.

I know I can throttle the operation, but even after throttling, the problem still exists if _drawPlot() runs for a long time.

Is there a way to control this?

3
  • Is _offset updated directly by the _drawPlot() function or by a different handler bound to a sort of "finished plotting" event triggered somewhere? A little bit of code may help Commented Jan 10, 2014 at 7:48
  • 5
    Yes, please add some code. JavaScript is indeed single-threaded, but it does feature asynchronous execution of code. The solution should be somewhere in the code, there's nothing to answer here based on what you've posted so far. Commented Jan 10, 2014 at 8:02
  • 2
    To get more help you can always post a jsfiddle jsfiddle.net Commented Jan 12, 2014 at 17:42

2 Answers 2

3
+50

There are cases where javascript in a browser will behave asynchronously - imagine loading resources over a network for example. In actual fact that is one of the things it does fairly well due to features like first class functions etc.

The short answer is - dont use global variables. Use objects and events to isolate the behaviours so that it doesnt matter what order they happen in. For example, having an offset property on 2 different objects instead of 1 that is reused for each event.

Sign up to request clarification or add additional context in comments.

2 Comments

Good point, but sometimes (and I bet this is the case) the order of execution is very important, so global variables (be they integer numbers or blocking queues, more or less directly accessible to the programmer) may become necessary, as you just can't synchronize on local varibles.
Yeah I agree - if a dragStart event fires before the dragEnd event then the order will be messed up regardless. In that case I would look into why the events are firing weirdly (could be down to the mouse leaving the dom element that should be catching the dragEnd event for example).
3

This is a problem I encounter VERY often in Javascript when using libraries like extjs or jQuery.

The only viable solution I came up until now is to handle the variable settings via locks. Sux big time for making but it is the only secure handling way. like

if (!this.lock) {
    this.lock = true;
    //do the actual function call
}

and on the finishing of the second event I put the unlock-er, works every time with code that runs a sync.

It is a flaw drawn from the concept of such event driven systems. if you need synced behavior in a event driven environment you have to put locks in place.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.