21

I am really struggling here to get to grips with writing asynchronous JavaScript. Could you please provide an example of a simple JavaScript function which is asynchronous written in plain JavaScript (and not using Node.js or JQuery)

Jasdeep Khalsa
  • 6,740
  • 8
  • 38
  • 58
  • @SLaks read Bergi's answer. That's basically what I am referring to. – Ryan Dec 10 '12 at 18:24
  • @ryan You're contradicting yourself. You said AJAX is the only "plain" Javascript that is asynchronous, but then you're agreeing with Bergi about the other types of asynchronous things in Javascript... – Ian Dec 10 '12 at 18:27
  • 1
    @ryan: But asynchrony has nothing to do with single-threaded-ness. Aside from Web Workers (obviously), all Javascript asynchrony is still single-threaded. – SLaks Dec 10 '12 at 18:27
  • 1
    Thanks for the comments guys but why the vote down of my question? - its these type of confusions about async I wanted to clear up for myself and others. – Jasdeep Khalsa Dec 10 '12 at 18:45
  • Is it possible to move this question to a more appropriate forum. This seems a valid question and both it and the answers are a useful, straight-forward resource. – Daniel Hollinrake May 01 '14 at 15:12

3 Answers3

34

JavaScript itself is synchronous and single-threaded. You cannot write an asynchronous function; plain JS has no timing API. There will be no side-effects from parallel threads.

What you can do is use some APIs provided by your environment (Node.js, Webbrowser) that allow you to schedule asynchronous tasks - using timeouts, ajax, FileAPI, requestAnimationFrame, nextTick, WebWorkers, DOM events, whatever.

An example using setTimeout (provided by the HTML Timing API):

window.setTimeout(function() {
    console.log("World");
}, 1000);
console.log("Hello");

Update: Since ES6 there are promises as an asynchronous primitive built into plain JavaScript, so you can do

 Promise.resolve("World").then(console.log); // then callbacks are always asynchronous
 console.log("Hello");

However, on their own they're not really helpful when there is nothing you could wait for (such as a timeout). And they don't change anything about the threading model either, all execution is run-to-completion without any events interfering midway.

Bergi
  • 630,263
  • 148
  • 957
  • 1,375
  • +1, very true; 'async' tasks are just the ones shifted in the execution queue. Hence the (sometimes) useful trick with `setTimeout(func, 0)`. ) – raina77ow Dec 10 '12 at 18:28
  • 2
    I thought async was less about timing and more about running a function or set of functions as a kind of background task so that the JavaScript interpreter need not wait to run the next function. Or in other words, running functions in parallel rather than in a series. Is that true? – Jasdeep Khalsa Dec 10 '12 at 18:50
  • 3
    @jasdeepkhalsa: No, the javascript itself does not run in parallel - it's always single-threaded (WebWorkers being the workaround). What happens in background is the waiting, the file access, the HTTP request etc. – Bergi Dec 10 '12 at 19:02
  • Hello from 2016: "JavaScript itself is synchronous" --- is this still kept after the `Promises` were added to the standard? – zerkms Aug 24 '16 at 05:12
  • @zerkms: I guess the answer needed an update, yeah – Bergi Aug 24 '16 at 05:23
8

This is asynchronous:

setTimeout(function(){
   console.log('1');
}, 2000);

console.log('2');

2 will be written to the console before 1. Because setTimeout is async.

Peter Rasmussen
  • 16,474
  • 7
  • 46
  • 63
7

Here's one very simple example:

for (var i = 0; i < 10; i++) {
  window.setTimeout(function() {
    console.log(i);
  }, 2000);
}

You might expect these console.log() calls to show you 0, 1, 2 etc., as in this snippet:

for (var i = 0; i < 10; i++) {
  console.log(i);
}

But in fact only 10s will be printed! The reason that functions passed into setTimeout function (as its 'callback' argument) will be invoked after for loop is completed - i.e., after i value is set to 10.

Yet you should understood one thing: all JavaScript in a browser executes on a single thread; asynchronous events (such as mouse clicks and timers) are only run when there's been an opening in the execution queue. Here's a brilliant article written by John Resig on this topic.

raina77ow
  • 103,633
  • 15
  • 192
  • 229
  • 6
    The problem with the loop is a scoping issue, not because of it's asynchronous nature. If they were scoped correctly, the loop would work as expected. Although it's a good explanation of the functions passed to `setTimout` executing _after_ the `for` loop – Ian Dec 10 '12 at 18:33