Asked  7 Months ago    Answers:  5   Viewed   23 times

I have been under the impression for that JavaScript was always asynchronous. However, I have learned that there are situations where it is not (ie DOM manipulations). Is there a good reference anywhere about when it will be synchronous and when it will be asynchronous? Does jQuery affect this at all?

 Answers

65

JavaScript is always synchronous and single-threaded. If you're executing a JavaScript block of code on a page then no other JavaScript on that page will currently be executed.

JavaScript is only asynchronous in the sense that it can make, for example, Ajax calls. The Ajax call will stop executing and other code will be able to execute until the call returns (successfully or otherwise), at which point the callback will run synchronously. No other code will be running at this point. It won't interrupt any other code that's currently running.

JavaScript timers operate with this same kind of callback.

Describing JavaScript as asynchronous is perhaps misleading. It's more accurate to say that JavaScript is synchronous and single-threaded with various callback mechanisms.

jQuery has an option on Ajax calls to make them synchronously (with the async: false option). Beginners might be tempted to use this incorrectly because it allows a more traditional programming model that one might be more used to. The reason it's problematic is that this option will block all JavaScript on the page until it finishes, including all event handlers and timers.

Tuesday, June 1, 2021
 
Gordnfreeman
answered 7 Months ago
20

I'd like to take a moment to address the premise of your question - that eval() is "evil". The word "evil", as used by programming language people, usually means "dangerous", or more precisely "able to cause lots of harm with a simple-looking command". So, when is it OK to use something dangerous? When you know what the danger is, and when you're taking the appropriate precautions.

To the point, let's look at the dangers in the use of eval(). There are probably many small hidden dangers just like everything else, but the two big risks - the reason why eval() is considered evil - are performance and code injection.

  • Performance - eval() runs the interpreter/compiler. If your code is compiled, then this is a big hit, because you need to call a possibly-heavy compiler in the middle of run-time. However, JavaScript is still mostly an interpreted language, which means that calling eval() is not a big performance hit in the general case (but see my specific remarks below).
  • Code injection - eval() potentially runs a string of code under elevated privileges. For example, a program running as administrator/root would never want to eval() user input, because that input could potentially be "rm -rf /etc/important-file" or worse. Again, JavaScript in a browser doesn't have that problem, because the program is running in the user's own account anyway. Server-side JavaScript could have that problem.

On to your specific case. From what I understand, you're generating the strings yourself, so assuming you're careful not to allow a string like "rm -rf something-important" to be generated, there's no code injection risk (but please remember, it's very very hard to ensure this in the general case). Also, if you're running in the browser then code injection is a pretty minor risk, I believe.

As for performance, you'll have to weight that against ease of coding. It is my opinion that if you're parsing the formula, you might as well compute the result during the parse rather than run another parser (the one inside eval()). But it may be easier to code using eval(), and the performance hit will probably be unnoticeable. It looks like eval() in this case is no more evil than any other function that could possibly save you some time.

Tuesday, June 1, 2021
 
turik
answered 7 Months ago
61

You may also checkout the UI.Layout jQuery plugin. Here's a demo.

Sunday, August 8, 2021
 
Scott Chantry
answered 4 Months ago
30

RequireJS always loads modules asynchronously but it allow a form of require that looks synchronous. Your second snippet is actually missing some really important code. (Also, the module name for jQuery is hardcoded to jquery. You could write a configuration that allows you to refer to it as jQuery but there's no point.) This form of the require calls is designed to be used inside modules so:

define(function (require) {
    var $ = require("jquery");
    $.doSomething();
});

What RequireJS does with the code above is transform it into this before executing it:

define(['jquery'], function (require) {
    var $ = require("jquery");
    $.doSomething();
});

Note the addition of the dependency as the first argument of define. When RequireJS executes the code, it finds the dependency, loads jquery and then calls the anonymous function. By the time require("jquery") is encountered the module is already loaded. At the end of the day while the require call looks synchronous, the loading of the module it requires still happens asynchronously.

Can you use this synchronous form require outside of a define call? Only if you are okay with failures. This require call will fail if the module passed to it is not already loaded. You get the infamous error:

Module name ... has not been loaded yet for context: ...

Using it in a define like I've shown above is safe. Or I guess you could do:

require(['jquery'], function (require) {
    var $ = require("jquery");
    $.doSomething();
});

which would work but what's the point of manually repeating the dependency. (In case you wonder, RequireJS does not transform a require call with a callback like the one I have in my example here in the same way it transforms a define call as I've shown above.)

Thursday, August 12, 2021
 
jenny
answered 4 Months ago
91

As I tried out and read through the link given by @konrad, I found that its a bug in Jquery UI - even in the latest version of it. The problem got solved as soon as I started using Jquery UI 1.9.2 version

here is the updated fiddle: http://jsfiddle.net/deveshz/YvmFf/2/

with same code:

var zindex = 10; 
$(".item").draggable({
    containment: "body",
    scroll: true,
    revert: function (event, ui) {
        $(this).css("border", "none");
        return !event;
   },
    start: function (event, ui) {
        $(this).css("z-index", zindex++);
        $(this).css("border", "2px solid #333");
    }
});

 $(".stack_items").droppable({
    hoverClass: "over",
    drop: function (event, ui) {
        $("<li class='item'></li>").html(ui.draggable.html()).appendTo(this);
        $(ui.draggable).remove();
    }
});

It uses Jquery version 1.9.2 from http://cdnjs.cloudflare.com/ajax/libs/jqueryui/1.9.2/jquery-ui.min.js

Wednesday, August 25, 2021
 
StampyCode
answered 4 Months ago
Only authorized users can answer the question. Please sign in first, or register a free account.
Not the answer you're looking for? Browse other questions tagged :  
Share