1

So I am currently trying to understand async javascript. And I learnt about async await, promises and callbacks. But in all examples they use setTimeOut() to generate a async call.

But my question is how do I write something like the setTimeOut function. For example I have a big calculation which takes time and I want it to not block the main thread. How would I go about making a function which just calculates a lot of stuff but is asynchronous?

I just can't wrap my head around this. Because it seems to me like it is only possible to write async code with network calls and so on, but I didn't find a way yet to write like an async for loop or something like this.

  • use callbacks with your main function ... – sathish kumar Mar 24 '19 at 10:26
  • With regular old javascript you don't, you just have one thread to work with. If you need to do this, you will need something like [web workers](https://developer.mozilla.org/en-US/docs/Web/API/Web_Workers_API/Using_web_workers) (or in node.js [child procceses](https://nodejs.org/api/child_process.html)) to spawn another thread/process. – Mark Mar 24 '19 at 10:31
  • They don’t use `Timeout()` to *generate* an asynchronous function, they use it **simulate** an action that takes time to be executed and thus demonstrating how async actually works – Davide Vitali Mar 24 '19 at 10:35
  • You write an async loop by doing a `setTimeout` between each iteration (or chunk of iterations). – Bergi Mar 24 '19 at 13:05

2 Answers2

1

It appears you didn't fully grasp what asynchronous is. The word itself says it's "not synchronized". That means there are moving parts that don't move at the same pace or speed. In case of JavaScript, it boils down to I/O (input/output) and CPU processing.

Network calls (xhr) are I/O calls that are slow compared to how fast CPU can process.

File system calls are I/O calls that are slow compared to how fast CPU can process.

Database queries are I/O calls that utilize the network and are slow compared to how fast CPU can process.

Logic with asynchronous code is "let the CPU do something else while this thing is travelling over the network or some other wire".

Why all this intro? Because you can't make a big calculation asynchronous. It utilizes CPU. You can, however, execute it in a service worker, have it utilize a different CPU core and it won't block the main thread.

Service worker intro: https://developer.mozilla.org/en-US/docs/Web/API/Service_Worker_API

Mjh
  • 2,904
  • 1
  • 17
  • 16
1

You can't¹. To do asynchronous tasks, you need some way to run the code on another thread, and that is impossible from within JavaScript.

setTimeout is asynchronous because it triggers an internal function written in some low level language (probably C++), which will then utilize hardware timers to trigger the callback to be called after some time.

fetch(...) for example is also asynchronous, because it will start an internal thread that writes and reads through your network card, and then calls back to the JavaScript engine when the request was done.


¹ that's a bit oversimplified. You could start multiple WebWorkers (multiple JavaScript engines running concurrently) to get some kind of multithreading. While the code still runs synchronous per thread, the two threads can execute concurrently and exchange information via messages, through that you can get asynchronous behaviour.

  // worker.js
  onmessage = function({ data }) { // called when messages from the other thread come in
    let start = Date.now();
    while(start + 3000 > Date.now()); // some long running action
   postMessage("done"); // go back to the other thread
 }

 // main.js
 const otherThread = new WebWorker("worker.js");
 otherThread.postMessage("go!"); // launch async task in other thread
 otherThread.onmessage = function({ data }) { // receive result
  console.log(data); // "done"
 });

WebWorker documentation

Jonas Wilms
  • 132,000
  • 20
  • 149
  • 151
  • Ok I think my question should then be how to write multithreaded code? – waterchiller Mar 24 '19 at 10:37
  • @waterchiller edited to include that – Jonas Wilms Mar 24 '19 at 10:43
  • Ok thank you very much. So this is basically what setTimeOut and network calls do? – waterchiller Mar 24 '19 at 10:45
  • @waterchiller yes, kind of, just that the code running in the other thread is not JavaScript but some compiled stuff that can also utilize the hardware directly. – Jonas Wilms Mar 24 '19 at 10:46
  • Ok thank you, seems kinda complicated. It is a lot easier to multithread in swift – waterchiller Mar 24 '19 at 10:48
  • @waterchiller you won't need it (like you do in Swift). I never had a real usecase for WebWorkers ... The JavaScript engine handles so many things for you already that younwould have to do manually in another language, it handles threads for you and offloads tasks (I/O, timers, rendering) to them – Jonas Wilms Mar 24 '19 at 10:51
  • Why would I not? Another question is this the same for nodeJs or is there a difference? – waterchiller Mar 24 '19 at 10:53
  • @waterchiller In NodeJS threads are a bit more powerful, but they work very similar to WebWorkers (you create two seperated scripts, and one starts the other). What is your usecase for multiple threads? – Jonas Wilms Mar 24 '19 at 10:54
  • Dont have a usecase yet just wanted to know because I didnt fully understand ir – waterchiller Mar 24 '19 at 10:56
  • @waterchiller One example I could give would be a game that I'm currently developing (together with some friends, so that isn't really "industry best practice"), as we are having to do a lot of calculations on the serverside we split the backend into multiple services: One does answer client requests and one does recalculate playerdata. They both operate onto the same database, they don't know each other and run in seperate NodeJS processes. Through that we offloaded work into multiple threads without having multithreading problems (we have to sync the db though) – Jonas Wilms Mar 24 '19 at 11:01
  • Most of the time you are just reacting to a user click, an incoming request or a timer, do a few very basic calculations and send a response, shedule other timers or change the UI. There are very rare cases were you actually have to do "heavy calculations", and in those rare cases you can spawn another self managed thread (which I haven't had the need for yet) – Jonas Wilms Mar 24 '19 at 11:03