Philip Roberts: What the heck is the event loop anyway? | JSConf EU 2014

By: JSConf

10393   47   422600

Uploaded on 10/09/2014

JavaScript programmers like to use words like, “event-loop”, “non-blocking”, “callback”, “asynchronous”, “single-threaded” and “concurrency”.

We say things like “don’t block the event loop”, “make sure your code runs at 60 frames-per-second”, “well of course, it won’t work, that function is an asynchronous callback!”

If you’re anything like me, you nod and agree, as if it’s all obvious, even though you don’t actually know what the words mean; and yet, finding good explanations of how JavaScript actually works isn’t all that easy, so let’s learn!

With some handy visualisations, and fun hacks, let’s get an intuitive understanding of what happens when JavaScript runs.

Transcript: http://2014.jsconf.eu/speakers/philip-roberts-what-the-heck-is-the-event-loop-anyway.html

License: For reuse of this video under a more permissive license please get in touch with us. The speakers retain the copyright for their performances.

Comments (45):

By anonymous    2017-09-20

Variable is innocent here. The problem is about the syncronization between javascript execution and DOM rendering. Although javascript is single threaded, DOM operations are being done by another thread and they wait each other.

So call stack has some code to execute and DOM rendering will wait the stack to be empty. But before that you are showing user an alert window which freezes everything. So the DOM's turn never comes until the user clicks the button on alert window.

A deferring method like the one Ibrahim has suggested, shifts the execution time of the block to the next JS event loop so the DOM can have one turn to update itself before that blocking code.

I suggest watching the related part of this video for more info.

Original Thread

By anonymous    2017-09-20

Setting innerHTML is synchronous, as are most changes you can make to the DOM. However, rendering the webpage is a different story.

(Remember, DOM stands for "Document Object Model". It's just a "model", a representation of data. What the user sees on their screen is a picture of how that model should look. So, changing the model doesn't instantaneously change the picture - it take some time to update.)

Running JavaScript and rendering the webpage actually happen separately. To put it simplistically, first all of the JavaScript on the page runs (from the event loop - check out this excellent video for more detail) and then after that the browser renders any changes to the webpage for the user to see. This is why "blocking" is such a big deal - running computationally intensive code prevents the browser from getting past the "run JS" step and into the "render the page" step, causing the page to freeze or stutter.

Chrome's pipeline looks like this:

enter image description here

As you can see, all of the JavaScript happens first. Then the page gets styled, laid out, painted, and composited - the "render". Not all of this pipeline will execute every frame. It depends on what page elements changed, if any, and how they need to be rerendered.

Note: alert() is also synchronous and executes during the JavaScript step, which is why the alert dialog appears before you see changes to the webpage.

You might now ask "Hold on, what exactly gets run in that 'JavaScript' step in the pipeline? Does all my code run 60 times per second?" The answer is "no", and it goes back to how the JS event loop works. JS code only runs if it's in the stack - from things like event listeners, timeouts, whatever. See previous video (really).

https://developers.google.com/web/fundamentals/performance/rendering/

Original Thread

By anonymous    2017-09-20

This is because getAllInWindow is a asynchronus function. This means that it will get pushed to a different heap (if I'm correct) to be excecuted. After the function is done, it gets pushed back to the Javascrip event loop, to be queued as the last item in the loop.

So what happens is: t1 gets called and you see an alert, the getAllInWindow gets called and pushed to the other heap. Then t3 gets called and alerted to the window. Now t2 has completed and pushed back into the event loop just to be excecuted as the third item in the row, and create some confusion for you :)

It might be good to read some more into this here: Javascript event loops This one helped me a lot to understand this situation: Philip Roberts: What the heck is the event loop anyway?

Original Thread

By stankot    2017-09-20

Hey there,

I'll start with the disclaimer, as lately HN comments have tendency of becoming toxic - everything I write is my personal opinion.

With that behind us I can start. I'll try to write this for someone who knows very little about JS, but knows her/his way around basic programming/cs.

Firstly I love JavaScript, I have been writing it for 10 years now, but there are bad parts of it as well.

Let's start with good stuff

* It is evolving in the right direction

* You can do a lot of things with it (web apps, games, mobile apps, server...)

* Materials for learning are everywhere

* It will be easy to find a job

Bad stuff

* It is moving at crazy to follow pace

* There are a lot of different ways of doing same things

* As it is very hip thing to do, there is a lot of bu___hit (beware of the hype train)

Learn plain javascript before moving to frameworks. Focus on ES6 and new stuff as it will make your life way easier.

* Someone already mentioned Dr. Axel Rauschmayer, pick any of his books - http://exploringjs.com/

* Another good one is You Dont Know JS - https://github.com/getify/You-Dont-Know-JS

Try to make small app on your own. You'll get into all sort of problems, but that's the fun part I guess. That will help you to understand what frameworks are trying to solve.

Then you can start learning one of the frameworks. React, Vue, Angular are all solid choices. My pick is React, as I know it best. Apply the same mindset as with learning plain JS. Try to write your own stuff on a small scale before importing huge libraries.

Good example is redux, everybody on the internet are screaming that you should always use it, but even Dan Abramov (author of redux) has great read - You might not need redux https://medium.com/@dan_abramov/you-might-not-need-redux-be4...

Try handling state yourself, then if you see that you need big guns, try redux. Same goes for any big library or technology.

So, buckle up, do it thoroughly and try to find fun in doing javascript. And the most important generic advice - do a real pet project instead of just blindly following tutorials.

This will take some time, and if you just want enough knowledge to lend a job, pick a framework, throw yourself into the deep end and swim your way out. This is something I wouldn't recommend but it works for some people.

Hope this helps, cheers! S

P.S.

Random JS talks I like

* Wat - Gary Bernhardt, 2012 https://www.destroyallsoftware.com/talks/wat It never fails to crack me up

* Live React: Hot Reloading with Time Travel - Dan Abramov, 2015 https://www.youtube.com/watch?v=xsSnOQynTHs Classic nowadays, it is a delight to watch Dan Abramov presenting, only thing missing is a mic drop at the end

* What the heck is the event loop anyway? - Philip Roberts, 2014 https://www.youtube.com/watch?v=8aGhZQkoFbQ This is a must watch for every js developer

EDIT: Sorry for the formatting, HN doesn't support markdown

Original Thread

By anonymous    2018-01-01

Glad it helped, in case you're interested in how event loop in node works you might want to take a look at [this link](https://www.youtube.com/watch?v=8aGhZQkoFbQ) and how callback comes in scene.

Original Thread

By anonymous    2017-09-23

You should watch this: https://www.youtube.com/watch?v=8aGhZQkoFbQ and check out this SO answer: https://stackoverflow.com/questions/21607692/understanding-the-event-loop

Original Thread

By anonymous    2017-09-23

For the reference and for anybody stumbling at this in the future, this is the explanation I was looking for:

There is no such thing as synchronous requests/join/waitFor in Javascript because everything runs on the same thread, even callbacks. Callbacks are added to event queue and processed after thread returns from outer scope. Waiting for whatever, had it been possible, would essentially cause a deadlock.

This video explains it nicely: Philip Roberts: What the heck is the event loop anyway?

Thanks guys and keep up the promises!

Original Thread

By anonymous    2017-10-01

Great answer by Patrick. I wanted to add few points.

To answer the question, why you are getting undefined at console.log(urls[i]) because the value of i is 4 and nothing is present at index 4.

Now to the point why i is 4. request is an async call and once you call request.get, it goes through event loop and gets written to the stack (with the right url) to be called. . This stack would be called only when the current call is over, which is after your for loop is over. Your loops gets over only when i is 4 and var is global scope

Here is a great video to understand how event loop works.

Original Thread

By anonymous    2017-10-08

@AlexanderArendar yes, this explains it https://www.youtube.com/watch?v=8aGhZQkoFbQ

Original Thread

By anonymous    2017-10-08

The problem

Your code isn't working the way you want because you are mixing async flow with sync flow.

When you call .then(), it will return this synchronously. Since setTimeout() is an async function that is called after some time (2 secs), this.value is still null.

If you want to know more about the asynchronous flow of JS, I recommend watching this video. It's a bit long but super helpful.


Making your code work

Since we can't tell when setTimeout() will call the function passed to it, we cannot call and callback functions that depend on its operations. We store these callbacks in an array for later consumption.

When the setTimeout() function is called (promise resolves), we have the result of promise resolution. And so, we now call all the bound callbacks.

class APromise {
    constructor(Fn) {
        this.value = null;
-       Fn(resolved => { this.value = resolved; });
+       this.callbacks = [];
+       Fn(resolved => {
+           this.value = resolved;
+
+           this.callbacks.forEach(cb => {
+               cb(this.value);
+           });
+       });
    }
    then(fn) {
-       fn(this.value);
+       this.callbacks.push(fn);
        return this;
    }
}

function myFun() {
    return new APromise(resolve => {
        setTimeout(() => { resolve('Hello'); }, 2000);
    });
}

const log = v => { console.log(v); };

myFun().then(log).then(log);

The chaining problem

The code above solves the problem partially.

True chaining is achieved when the result of one callback is passed on to the next. That's not the case in our current code. TO make that happen, each .then(cb) must return a new APromise that resolves when the cb function is called.

A complete and Promises/A+ conformant implementation is way over the scope of a single SO answer, but that shouldn't give the impression that it isn't doable. Here's a curated list of custom implentations.


Fuller implementation

Let's start with a clean slate. We need a class Promise that implements a method then which also returns a promise to allow chaining.

class Promise {
    constructor(main) {
        // ...
    }

    then(cb) {
        // ...
    }
}

Here, main is a function that takes a function as an argument and calls it when the promise is resolved/fulfilled - we call this method resolve(). The said function resolve() is implemented and provided by our Promise class.

function main(resolve) {
    // ...
    resolve(/* resolve value */);
}

The basic feature of the then() method is to trigger/activate the provided callback function cb() with the promise value, once the promise fulfills.

Taking these 2 things into account, we can rewire our Promise class.

class Promise {
    constructor(main) {
        this.value = undefined;
        this.callbacks = [];

        const resolve = resolveValue => {
            this.value = resolveValue;

            this.triggerCallbacks();
        };

        main(resolve);
    }

    then(cb) {
        this.callbacks.push(cb);
    }

    triggerCallbacks() {
        this.callbacks.forEach(cb => {
            cb(this.value);
        });
    }
}

We can test our current code with a tester() function.

(function tester() {
    const p = new Promise(resolve => {
        setTimeout(() => resolve(123), 1000);
    });

    const p1 = p.then(x => console.log(x));
    const p2 = p.then(x => setTimeout(() => console.log(x), 1000));
})();

// 123 <delayed by 1 second>
// 123 <delayed by 1 more second>

This concludes our base. We can now implement chaining. The biggest problem we face is the the then() method must return a promise synchronously which will be resolved asynchronously.

We need to wait for the parent promise to resolve before we can resolve the next promise. This implies that instead of adding cb() to parent promise, we must add the resolve() method of next promise which uses return value of cb() as its resolveValue.

then(cb) {
-   this.callbacks.push(cb);
+   const next = new Promise(resolve => {
+       this.callbacks.push(x => resolve(cb(x)));
+   });
+
+   return next;
}

If this last bit confuses you, here are some pointers:

  • Promise constructor takes in a function main() as an argument
  • main() takes a function resolve() as an argument
    • resolve() is provided by the Promise constructor
  • resolve() takes an argument of any type as the resolveValue

Demo

class Promise {
    constructor(main) {
        this.value = undefined;
        this.callbacks = [];

        const resolve = resolveValue => {
            this.value = resolveValue;

            this.triggerCallbacks();
        };

        main(resolve);
    }

    then(cb) {
        const next = new Promise(resolve => {
            this.callbacks.push(x => resolve(cb(x)));
        });

        return next;
    }

    triggerCallbacks() {
        this.callbacks.forEach(cb => {
            cb(this.value);
        });
    }
}

(function tester() {
    const p = new Promise(resolve => {
        setTimeout(() => resolve(123), 1000);
    });

    const p1 = p.then(x => console.log(x));
    const p2 = p.then(x => setTimeout(() => console.log(x), 1000));
    const p3 = p2.then(x => setTimeout(() => console.log(x), 100));
    const p4 = p.then((x) => new Promise(resolve => {
        setTimeout(() => resolve(x), 1000);
    }))

    /*
        p: resolve after (1s) with resolveValue = 123
        p1: resolve after (0s) after p resolved with resolveValue = undefined
        p2: resolve after (0s) after p resolved with resolveValue = timeoutID
        p3: resolve after (0s) after p2 resolved with resolveValue = timeoutID
        p4: resolve after (1s) after p resolved with resolveValue = Promise instance
    */
})();

// 123  <delayed by 1s>
// 2    <delayed by 1.1s>
// 123  <delayed by 2s>

Original Thread

By anonymous    2017-10-08

TL;DR: You must use AJAX.

Your problem is actually not solvable with the approach you are taking. You cannot do anything in the UI once you make an HTTP request that is not an XMLHTTPRequest, because it will cause render blocking on the page since it's synchronous.

You have two potential solutions:

  1. Add a time gap between the time a user clicks the button and the request is made
  2. Use AJAX

Number 1 won't give you the desired effect at all because if you animate your loading bar on click, and then after it's reached 100% you begin the HTTP request, your loading bar animation is complete BEFORE the request is actually made, and that defeats the whole purpose of having a loading bar.

This means you need to use AJAX.

If you want to understand more on why this won't work for you without AJAX, watch this video.

In short, the browser stops rendering (painting) anything in the screen because it's blocked by another action, which in this case for you will be the synchronous HTTP request. So while the synchronous HTTP request is being made, no loading bar can be animated since painting is blocked by the browser.

If you want to test this out for yourself, add a button on your page that requests a page that takes a long time to load. While the native browser spinner is loading, you will not be able to click anything else on the page because the render is being blocked. That same blocking is the very reason you can't animate a loading bar in this scenario.

Original Thread

By anonymous    2017-10-08

The goal is to generate a random color in the Hex format. My attempt to explain the code you provided us with:

When randColor is called it is added to the call stack and then gets paused waiting for the nested function's calls to complete.

That nested function co(lor) is IIFE and it is called recursively. Initially an empty string is passed in and the local lor variable is assigned to it.

Math.floor(Math.random()*16) - generates numbers from 0 to 15 which are the indexes of the array [0,1,2,3,4,5,6,7,8,9,'a','b','c','d','e','f']. At each step a new symbol from the array is added to the local lor string passed in as a parameter earlier. Updated string is passed further into a new call if its length is fewer than 6.

The nested function's recursion adds to the call stack objects with lor values like this (for example):

5aTh46 (top, last call, gets popped out first)
5aTh4
5aTh
5aT
5a
5      (first call)

when the length of the local lor variable gets equal to 6 after the 6th call, then base condition lor.length == 6 is fulfilled and 5aTh46 string is returned from the top of the call stack. So, for the 5th call we have

return (lor += [0,1,2,3,4,5,6,7,8,9,'a','b','c','d','e','f'] [Math.floor(Math.random()*16)]) && (lor.length == 6) ? lor /* = 5aTh4*/ : co(lor) /* = 5aTh46*/;

lor.length == 6 is false since local lor is equal to 5aTh4. So, 5aTh46 returned by the 6th call is returned after the 5th call as well and so forth untill value 5aTh46 is finally returned as a result of co(lor)'s calls and added to the # string inside randColor. In the end we get #5aTh46.

PS. That's how I understand it. If you get the concepts of event loop and IIFE this explanation may sound simple :)

Original Thread

By anonymous    2017-10-15

I think it has to do with javascript's event loop. With the link you can watch amazing video about event loop in JS. I'm not sure, but it seems like what's inside resolve() is called asynchronously, but for loop is sync, that's why what's inside resolve is put into a queue and for loop is executed immediately. After "normal" execution process finished, resolve does it's job, returning 5.

In the example with setTimeout you've put the code into queue, but for later(2000ms) execution. Since 5 doesn't do anything, it's returned right away(asynchronously though) and after 2 seconds your code is run. Wath the video.

Original Thread

By anonymous    2017-10-22

Where is the asynchronousness of netty coming from?

Netty adopted the principle of eventloops which you may known from a language like JavaScript. This allows netty to work fully asynchronous. (For more information about eventloops and the basic underlying principle I would recommend this video about the evenloop in JavaScript)

What do I need on the client side to benefit from the asynchronousness?

  1. Client sends request (containing payload and request id = clientside incrementing integer)
  2. Server process the request for 50sec
  3. Server sends response (containing the payload and the same request id the client send in his request)
  4. Client receives the response and looks up the request id (If the client is able to find the request id and its underlying callback it will invoke it)

Hope that helped

Original Thread

By anonymous    2017-10-30

Here is the flow of execution, This should clear all your doubts

// 1. This function will be called as soon as clicked
updateField(){
    this.textContentMain.title = "test" // 2. changes the value
    this.asyncTestFunction(); // 3. call async function
    for(var i=0;i<3999999999;i++){ // 5. start for loop 

    } 
    // 6. end for loop
}

asyncTestFunction() {
    this._contentSalesTextConfigService.get(this.contentSalesTextConfig) // 4. call the http request
    .subscribe(item => {
        this.textContentMain.title = "asynced"; // 7. asap response is received and for loop finish its execution this wiil be executed.
    })
}

Why => 7. asap response is received and for loop finish its execution this wiil be executed. (why it waits for "for loop" to finish)?

For this you have to read event-loop
Watch this the best video which can explain the key thing behind the scene:

What the heck is the event loop anyway?

Original Thread

By anonymous    2017-10-30

Can I say that, NodeJS async model is similar to [chrome-V8](https://www.youtube.com/watch?v=8aGhZQkoFbQ) async model? I think, I don't agree with your final definition of Asynchronous IO

Original Thread

By anonymous    2017-10-30

Javascript is not a sequential language per se. When you use promises and callbacks, the execution order goes out the window. In this instance if you want to use the resulted ID, you will have to continue your code inside the then's function.

var doSomethingWithId = function(id) {
  doSomething()
};

chatRooms.save(chatData).then(function(res){
  console.log("save chat", res);
  doSomethingWithId(red._id);
});

Unfortunately there's not many ways around it.

You could use ES6's async/await syntax to streamline the code, but that will introduce a lot of other problems (transpiling, etc).

To understand how the language works, I recommend watching this video: https://www.youtube.com/watch?v=8aGhZQkoFbQ

Original Thread

By anonymous    2017-11-06

See, Js is single threaded. So, it is managing tasks as asynchronous by event loop(video which explains what is event loop). you are giving the callback for the getCurrentPosition. So, I guess it is a asynchronous function. it will execute after your third console. So, you are confused with the order. I clarified the order in your code. think that's way will help you to understand what happens here. This problem is not with the scoping.

<script>
function getMyLocation() {
    found = 0;
    if (navigator.geolocation) {
        console.log(found); // order ::: 1
        navigator.geolocation.getCurrentPosition(function(position) {
            found = 1;
            console.log(found); // order ::: 3
        });
    }
console.log(found); // order ::: 2
}
</script>

Original Thread

By anonymous    2017-11-13

Your code won't work because it is async code.

Watch the famous Youtube video about the event loop

But in short, if you will run the following example, which is like your code but without your logic:

var User = require('./user.model');

class UserDao {
constructor() {}

insert(user) {
    var pk; 
    console.log('1');
    User.sync({ force: false }).then(() => {
        pk = 123;
        console.log('3'); 
    });
    console.log('2');
    return pk; 
}

The variable pk will be undefined and your console will look like this:

1
2
3

If you want it to work, you should "wait" for the async functions like this:

var User = require('./user.model');

class UserDao {
    constructor() {}

    // @return Promise
    insert(user) {
         return User.sync({ force: false }).then(() => {
             return User.create(user)
         }).then((user) => {
             console.log('Entry successful from dao: ' + JSON.stringify(user));
             return user.id
         })
    }

And when you use it:

class UserDaoTest {
    constructor() {
        this.userDao = new UserDao();
        this.compare = new UtilsObject();
    }

    /*
        all CRUD method calls
    */
    testAll() {
        // if testInsert and testUpdate can run simultaneously you can keep it like this. 
        // Otherwise, use Promise.then as well
        this.testInsert();
        this.testUpdate(); 
    }

    /*
        insert method
    */

    testInsert() {
        var user = {
            // ...
        };

        /*
            calling insert user with above data
        */
        this.userDao.insert(user).then((userId) => {
            // YOUR COMPARE CODE
        }).then(done); // Where done is a function to let you test framework that you async code is done
    }
}

export default UserDaoTest;

Another way of doing that is using the new async and await. That way you will get a code which is more readable and maintainable.

You can read more here

Original Thread

By anonymous    2017-11-20

What Jonas said. Something really worth understanding is the Event Loop: https://www.youtube.com/watch?v=8aGhZQkoFbQ

Original Thread

By anonymous    2017-11-27

The lexical scope of var i; is the window in this case (var is a function scope and not block scope).

So in the first loop, by the time the setTimeout callback is invoked, the i variable is already at the value of 6. Hence it will log g twice.

In the second loop you create a new function instance on each iteration that closes over the k variable, thus create a new instance of this variable in memory. when the setTimeout callback is invoked it has access to the relevant k object which is 0 is the first call and 2 in the second call.

In the third loop you are using let instead of var which uses the block scope.
So the same flow happens like in the second loop, but no need for a new function instance this time to close over the variable.

Edit
As a followup to your comment:

When the first callback is created i is in scope and has value of 0. Then at some point the callback is invoked and it checks out the value of i in it's outer lexical environment at time of creation. This 'at time of creation' bugs me , because the way i understand it , it would mean that i should be 0 , not 6, as actually it is.

The setTimeout callback doesn't know nothing about i when it was "created" it only accessing its value in memory when the callback is invoked.
The key point here to remember is that the setTimeout will invoke the callback only after the for loop has finished ALL iterations. This is because the setTimout is calling the callback in another event loop. I really recommend watching this video that explains in great details about the event loops.

Because i is in the same scope on each iteration the callback will get the final i "version" which is the value of 6.

Just to illustrate the situation, it's as if your code would look like this for the first example:

var i;

for(i =0; i < 4; i++){
  // not important 
}

console.log(i);
console.log(i);

In the other loops examples you create different new scope for each counter (k for the 2nd loop example and j for the 3rd example). And when the callback gets invoked it has access to the relevant scope.

Original Thread

By deadcoder0904    2018-04-17

Philip Roberts: What the heck is the event loop anyway? | JSConf EU 2014 - https://www.youtube.com/watch?v=8aGhZQkoFbQ

Original Thread

By anonymous    2017-12-04

The difference between both buttons is the `setTimeout` on the second button will "push" the execution to the end of the Que in the event loop. i strongly recommend watching [this video](https://www.youtube.com/watch?v=8aGhZQkoFbQ) about event loops.

Original Thread

By anonymous    2017-12-04

JavaScript is single threaded, non-blocking and asynchronous language. JavaScript has call stack, event loop and a callback queue. Words are taken directly from this video. Javascript works on v8 engine (chrome), spider monkey (firefox) which provide JavaScript call stack and heap. v8 or spider monkey provide call stack to Javascript so whenever a function is called, it is stored in the call stack of the runtime (browser in our case, local if you have node installed). Browser also provide the web apis to the javascript like setTimeOut, XMLHttpRequest and DOM. The pictorial illustration is something like this. (Source is the same video which I've tagged.)

enter image description here

JavaScript is single threaded and it means it can execute one function at a time as it has only one call stack. So whenever an asynchronous code (inside func1)is executing, it is executed through webAPIs provided by the browser. The role of callback queues come here. Whenever the result from the Async code is executed, it is stored in the callback queue and it waits for the stack to get empty (event driven programming). Whenever it sees that the stack is empty, the function from the callback queues will start executing.

In your case, you're calling func1, it kicks in some async code but currently func1 is in stack. If the async code has completed and if it sees the stack as empty, it will executed the async code first and then func2 but if the async code hasn't completed, it will start executing the func2 and the callback queue will wait for the stack to get empty. In this case, the flow will be func1 --> func2 --> async code.

So, it is matter of timing. For async code, if the code has returned and waiting in callback queue, as soon as it sees the stack empty, it will kick in and start executing the callbacks (.then or callback from setTimeOut etc.) I'll recommend you to watch that video for better insights and what an event loop in JS is. If I'm missing out something, anyone please feel free to edit this answer or provide suggestions for edit.

Original Thread

By anonymous    2017-12-11

nextTick allows you to do something after you have changed the data and VueJS has updated the DOM based on your data change, but before the browser has rendered those changed on the page.

Normally, devs use native JavaScript function setTimeout to achieve similar behavior. But, using setTimeoutrelinquishes control over to the browser before it gives control back to you via your callback.

Let's say, you changed some data. Vue updates DOM based on the data. Mind you the DOM changes are not yet rendered to the screen by the browser. If you used nextTick, your callback gets called now. Then, browser updates the page. If you used setTimeout, your callback would get called only now.

You can visualize this behavior by creating a small component like the following:

<template>
  <div class="hello">
    {{ msg }}
  </div>
</template>

<script>
export default {
  name: 'HelloWorld',
  data() {
    return {
        msg: 'One'
    }
  },
  mounted() {
      this.msg = 'Two';

      this.$nextTick(() => {
          this.msg = 'Three';
      });
  }
}
</script>

Run your local server. You will see the message Three being displayed.

Now, replace your this.$nextTick with setTimeout

setTimeout(() => {
    this.msg = 'Three';
}, 0);

Reload the browser. You will see Two, before you see Three.

Check this fiddle to see it live

That's because, Vue updated the DOM to Two, gave control to the browser. Browser displayed Two. Then, called your callback. Vue updated the DOM to Three. Which the browser displayed again.

With nextTick. Vue udpated the DOM to Two. Called your callback. Vue updated the DOM to Three. Then gave control to the browser. And, the browser displayed Three.

Hope it was clear.

To understand how Vue implements this, you need to understand the concept of Event Loop and microtasks.

Once you have those concepts clear(er), check the source code for nextTick.

Original Thread

By anonymous    2017-12-11

I've updated your question with the answer since it is a duplicate question. You should learn about asynchronous processing in javascript (promises) https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise and the event loop: https://www.youtube.com/watch?v=8aGhZQkoFbQ&t=717s You can delete this question as it's a duplicate and would get rid of the down vote.

Original Thread

By anonymous    2018-01-22

Unfortunately, not really, this is because of how the browser engine decides to repaint the screen. Without the timeout, the browser engine recognizes it's going to do a bunch of updates (adding the dots to the DOM). Because repainting the screen is expensive, it waits to do as much as possible at one time, and, in your case, all of the dots show up at once. With the timeout added, each call to your function gets "deferred" for future execution.

This may or may not happen "right away" and is non-trivial to explain in detail so I would recommend watching this video https://www.youtube.com/watch?v=8aGhZQkoFbQ which explains the JS event loop or read some articles on browser reflow:

Without changing much of what you've already done, one solution is to batch a few of the dots to be drawn together. I've added a for loop to your function which will make five dots get drawn together. Adjust this to 10, 20, or higher and you'll see the dots get painted even faster. I hope there is a number that you'll find suitable. I understand you may want to just speed up the drawing of every dot individually, but bear in mind that screens have refresh rates, so the faster you want the routine to finish the more they will appear in batches any way.

var dotCellSize;
var initialOffset;
var slotsHorizontally;
var slotsVertically;
var container;
var redDots;
var dots;

var newDotElement = $('<div class="dot">');

function randomInteger(min,max)
{
	return Math.floor(Math.random() * (max - min + 1)) + min;
}

function addDots()
{
	if (!dots.length)
		return;
	
  for (let i = 0; i < 5; i++) {
    var dotIndex = randomInteger(0, dots.length - 1);
    var dot = dots[dotIndex];

    dots.splice(dotIndex, 1);

    var column = dot % slotsHorizontally;
    var row = Math.floor(dot/slotsHorizontally);

    var position = {
      left: initialOffset + column*dotCellSize,
      top: initialOffset + row*dotCellSize
    };

    var dotElement = newDotElement.clone().css(position);

    if (-1 != redDots.indexOf(dot))
      dotElement.addClass('red');

    dotElement.appendTo(container);
  }
    setTimeout(function() {
      addDots();
    }, 1);
}

function generateDots(dotContainer, cellSize, numberOfRedDots)
{
	container = dotContainer;
	dotCellSize = cellSize;
	dots = [];
	redDots = [];
	
	container.find('div.dot').remove();
	
	numberOfRedDots = typeof numberOfRedDots !== 'undefined' ? numberOfRedDots : 3;
	
	initialOffset = Math.floor(dotCellSize/2);

	slotsHorizontally = Math.ceil(container.width()/dotCellSize);
	slotsVertically = Math.ceil(container.height()/dotCellSize);

	var numberOfSlots = slotsHorizontally*slotsVertically;
	
	while (dots.length < numberOfSlots)
		dots.push(dots.length);

	while (redDots.length < numberOfRedDots)
	{
		var newRedDot = randomInteger(0, numberOfSlots - 1);
		
		if (-1 == redDots.indexOf(newRedDot))
			redDots.push(newRedDot);
	}
	
	addDots();
}

generateDots($('.dot-container'), 18, 15);
.dot {
  width: 4px;
  height: 4px;
  border-radius: 50%;
  background-color: #C0E3EA;
  position: absolute;
  z-index: 1;
}

.dot.red {
  background-color: #EF3D48;
}

.dot-container {
  width: 420px;
  height: 280px;
  background-color: #333;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="dot-container"></div>

Original Thread

By anonymous    2018-01-01

If you're even more interested, https://stackoverflow.com/questions/38752620/promise-vs-settimeout https://www.youtube.com/watch?v=8aGhZQkoFbQ

Original Thread

By anonymous    2018-01-01

As new member, I'm unable to comment on topics, that's why I had to create a new topic. But in this way, I can clarify the problem, so hopefully you guys can help me.

I have read quite a lot about Node.js Event Loop. And I have shaped my understanding of it based on following materials:

Node.js Event Loop
What the heck is the event loop anyway?
Why setImmediate() execute before fs.readFile() in Nodejs Event Loop's works?

(Please feel free to suggest other materials which are informative and accurate)

Especially the third link, has given me a better understanding. But keeping that in mind, I'm unable to understand Event Loop behavior for the following code:

var fs = require('fs');
var pos = 0;

fs.stat(__filename, function() {
 console.log(++pos + " FIRST STAT");
});

fs.stat(__filename, function() {
 console.log(++pos + " LAST STAT");
});

setImmediate(function() {
 console.log(++pos + " IMMEDIATE")
})

console.log(++pos + "LOGGER");

Surprisingly, for me output is as follow:

LOGGER  
FIRST STAT  
LAST STAT  
IMMEDIATE

screenshot of my terminal, showing output as well as node version
screenshot of output from online code compiler rextester.com

Keeping the Event Loop Diagram in mind, I guess flow should be as follow:

  1. Interpretor firstly starts two stat operations.
  2. Interpreter en-queues setImmedate callback (event) in the setImmedate queue
  3. Call stack logs the logger
  4. All event queues before I/O Poll phase are empty, so Event Loop(EL) moves on
  5. In I/O Polling phase, EL collects the events and enqueues both the fs.stat callbacks in the "run completed I/O handlers" phase
  6. EL checks the Check phase, and run the setImmediate callback
  7. This round of EL ends, and second round starts
  8. In "run completed I/O handlers", EL runs both callbacks (order of them can is onn-determinstic)

Question 1: Which part of my analysis/prediction is wrong?

Question 2: At which point, does Event Loop start working? Does it start from the beginning of the app (i.e. stage 1)? or does it start once the whole code is read by interpreter, all sync tasks are done within Call Stack, and Call Stack needs more task, i.e. between stage 3-4?

Thanks in advance,

Original Thread

By anonymous    2018-01-07

https://www.youtube.com/watch?v=8aGhZQkoFbQ is a very good talk that explains the subject quite well.

Original Thread

By anonymous    2018-01-07

Glad to help! :-) I highly recommend this video about Javascript's event loop - https://www.youtube.com/watch?v=8aGhZQkoFbQ - it is a fantastic (and fun) explanation of async code in JS. Good luck!

Original Thread

By anonymous    2018-01-29

The problem

The order that he code will execute is not in the same order you write it. This is called async. Meaning the request.get gets fired away and then later resolved.

You are hoping for this.

  1. Read file.
  2. Go through first item.
  3. Request data for the first item (it fires away)
  4. Recieve data for first item (it resolves)
  5. Go through the second item.
  6. Request data for the second item (it fires away)
  7. Recieve data for second item. (it resolves)

What is happening is more like this:

  1. Read file.
  2. Go through first item.
  3. Request data for the first item (it fires away)
  4. Go through the second item.
  5. Recieve data for FIRST item (it resolves)
  6. Request data for the second item (it fires away)

See how the order is different? Your code goes to the second item before it recieves the data from the first. This is because you're asking a webserver for some data. Meanwhile your code keeps on running and then the webservers says "hey here's the data you asked for".

Imagine setting the table and you're putting the forks on the table and ask me to bring the knives. Do put one fork, wait for me to bring one knife. You put another fork, wait for me to bring a knife, etc.

OR

Do you ask me for the knives and meanwhile put all the forks on the table and don't wait for me. When I arrive with the knives you put them on the table.

The solution 1) Check out async/await: https://tutorialzine.com/2017/07/javascript-async-await-explained

OR

2) Reduce the promise: https://gist.github.com/anvk/5602ec398e4fdc521e2bf9940fd90f84

In addition https://www.youtube.com/watch?v=8aGhZQkoFbQ

Original Thread

By anonymous    2018-02-12

In your example the reject function doesn't work because javascript is single threaded.

In reality, the setTimeout function is working, but runs outside of the javascript thread(in browser queue system, or in your case by the node.js queue system (libuv), when setTimeout finished, the handler (the code you want to execute when the timeout finish) is inserted in a event queue and prepared to be executed for javascript throught the event loop, but, the problem is that the event loop is processing the code of your synchronous code, and never reach your handler.

This is an "homemade" example to stops a infite loop:

function longTimeFunction(timeAllowedInSeconds) {
    function getCurrentTime() {
        return new Date().getTime() / 1000;
    }

    const startTime = getCurrentTime();
    let stopLoop = false;
    let currentTime;

    while(1 && !stopLoop) {  //infinite loop
        //your code here, for example:
        console.log(Math.random());

        currentTime = Math.round(getCurrentTime() - startTime);

        if (currentTime >= timeAllowedInSeconds) {
            stopLoop = true;
        }
    }
};

longTimeFunction(3);

To help you understand the how deal with sync and async in javascript I put here one amazing video:

Philip Roberts: What the heck is the event loop anyway? | JSConf EU 2014

Original Thread

By anonymous    2018-02-12

@MelBlanc: no, there isn't a function that "iterates the delay". You just set the timer, the function fires and at the end of it you set up another timer. As for understanding what happens, you definitely need a good material on that, e.g. https://www.youtube.com/watch?v=8aGhZQkoFbQ

Original Thread

By anonymous    2018-02-18

As javascript is single threaded, so your genSalt() will be pushed into event loop and it won't wait for a response and jump to next statement. and after your gensalt() will finish it's execution it's callback function(err, hash) {...}); will be executed. Write your code in the callback of a genSalt() method like this:

bcrypt.genSalt(10, function (err, salt) {
    bcrypt.hash(req.body.password, salt, function (err, hash) {
        req.body.password = hash;
        globalpasswordholder = req.body.password;

        user.password = globalpasswordholder;
        user.resetPasswordToken = undefined;
        user.resetPasswordExpires = undefined;

        user.save(function (err) {
            req.logIn(user, function (err) {
                done(err, user);
            });
        });
    });
});

And bcrypt.genSalt also provides promisified method so you can also use it like this:

var globalpasswordholder;
bcrypt.genSalt(10)
        .then(salt => {
            return bcrypt.hash(req.body.password, salt);
        })
        .then(hash => {
            req.body.password = hash;
            globalpasswordholder = req.body.password;

            user.password = globalpasswordholder;
            user.resetPasswordToken = undefined;
            user.resetPasswordExpires = undefined;

            return user.save();
        })
        .then(() => {
            req.logIn(user, function (err) {
                done(err, user);
            });
        })
        .catch(e => console.log(e));

This is a good video to understand the concepts.

Original Thread

By anonymous    2018-02-18

I would also suggest watching this great explanation of event loop https://www.youtube.com/watch?v=8aGhZQkoFbQ

Original Thread

By anonymous    2018-02-26

To understand why you cannot just throw an error from within the callback of setTimeout you need to understand a few concepts.

The Stack

As a program is running information is stored in a data structure called the stack. When a method is called information is stored on the stack until the method returns. Since methods generally contain calls to other methods the stack grows and shrinks until all the methods have returned (this is generally the end of the program). When an error is thrown it is passed down the stack of function calls that have yet to return until it is caught and handled, or reaches the "main" method, which generally causes the program to crash.

The Event Loop

The event loop is what powers the asynchronous functionality in Javascript. When setTimeout or any other asynchronous method is called the callback is placed in a queue called the event loop. As the javascript runtime executes the program and reaches the end of the stack (e.g. all methods have returned) instead of merely exiting the program it first looks to see if there is anything in the event loop, if there is it begins executing it causing the stack to grow and shrink once more. When there is nothing left in the event loop, and the stack is empty then the program is free to exit.


This means that when you call setTimeout the callback that is passed into the method ends up being executed in a different stack frame. This means that it is impossible for the error to be thrown down the stack and be caught by the promise, because the stack the promise was created in has already finished executing and is no more.

I would suggest watching this video on the topic, it goes into great detail and helps you visualize what is going on: What the heck is the event loop anyway?

Original Thread

By anonymous    2018-02-26

And if you want to understand why the spinner is not turning on ... here is a great video on understanding JavaScript event loops: https://www.youtube.com/watch?v=8aGhZQkoFbQ&t=9s

Original Thread

By anonymous    2018-02-26

In order to understand async function, you should understand what is event loop.

The easiest example:

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

But even the console.log is async. Check the video above and you will understand the basics.

Original Thread

By anonymous    2018-03-18

They run outside of the JavaScript runtime. Those "Web API's" are executed within the browser's Web API execution space.

setTimeout() for example, is a method of the window object (it can also be invoked as window.setTimeout()). window is not at all part of JavaScript (it's a browser object) and anything you ask the window to do for you is handled outside of the JavaScript runtime and by the browser's other capabilities. The request for the Web API call originates from within the JavaScript environment, but the execution of the API call actually runs outside of it.

This is the very reason that we can have asynchronous behavior in web applications. While the JavaScript runtime (which is a synchronous environment that can only do one thing at a time) is doing its one thing, the browser can be doing something else.

setTimeout(), alert(), navigator.geolocation, XMLHttpRequest are all examples of Web APIs that run outside of the JS engine.

Here are some other Web API's and here is a great video that explains this in the context of timers specifically.

Original Thread

By anonymous    2018-03-18

The problem has to do first with JavaScript's single threaded run-to-completion guarantee in that code in a function is guaranteed to execute uninterrupted from start to finish.

And second with how the event loop works, where you have a queue of macro-tasks (timeouts, mouse, keyboard events) and a queue of micro-tasks (promises, DOM manipulation). Browsers may split them into more queues for performance gains though.

The fundamental difference being that only one macro-task is executed in each round of the loop (i.e. you'd want keystrokes to be handled one at a time rather that suddenly happen at the same time), while all micro-tasks currently in the queue need to be cleared before the next round (i.e. you'd want previously triggered DOM updates to happen before the next mouse event or keystroke).

Even if promises resolve immediately, they still get added to the queue and always execute after the function who invoked them runs to completion.

There are a few ways you could solve it, as mentioned in the comments by karthick, you could make the array update after all promises fulfil which will ensure that the array updates are always the last entry of the queue and for which you wouldn't even need a closure on the array:

'use strict';
var arr1 = [2, 4, 6, 8, 10];
var arr = [];

function putItem(i) {
    function returnResult() {
        return new Promise(
            (resolve, reject) => {
                let thisObject = {
                    array: arr1,
                    index: i
                }
                console.log("Async code started: putting item arr1[" + thisObject.index + "] = " + thisObject.array[thisObject.index]);
                setTimeout(function () {
                    arr.push(thisObject.array[thisObject.index]);
                    resolve(thisObject); // "Release" the protected resource (arr1[i])
                }, Math.random() * 2000 + 1000);
            }
        );
    }
    return returnResult();
}


var foo = putItem(2).then(function (result) {
    console.log(result.array[result.index] + " was inserted")
});


var bar = putItem(3).then(function (result) {
    console.log(result.array[result.index] + " was inserted")
});
   
Promise.all([foo, bar]).then(responses => arr1[3] = 7);

setTimeout(() => {
    console.log(arr);
}, 3000);

That is, however, assuming you have control over the array updates, if you're unable to schedule them after the promises fulfilment then you can add the following, I noticed on your original example that you were doing

var temp_arr = arr;

But even if that creates a closure, it's closing on a reference value which is the case for all non-primitive types in JS, you'll need to clone it in order to keep the same values.

Then, I noticed you're not really using the temp variable, and once you clone the array, the function it's not technically a closure anymore cause it owns its own version of the variable.

So here's the sample code, similar to what you had but just removing the temp_arr and cloning the arr1 using the spread operator in thisObject.

'use strict';
var arr1 = [2, 4, 6, 8, 10];
var arr = [];

function putItem(i) {
    function returnResult() {
        return new Promise(
            (resolve, reject) => {
                let thisObject = {
                    array: [...arr1],
                    index: i
                }
                console.log("Async code started: putting item arr1[" + thisObject.index + "] = " + thisObject.array[thisObject.index]);
                setTimeout(function () {
                    arr.push(thisObject.array[thisObject.index]);
                    resolve(thisObject); // "Release" the protected resource (arr1[i])
                }, Math.random() * 2000 + 1000);
            }
        );
    }
    return returnResult();
}


const foo = putItem(2).then(function (result) {
    console.log(result.array[result.index] + " was inserted")
});


const bar = putItem(3).then(function (result) {
    console.log(result.array[result.index] + " was inserted")
});
   
Promise.all([foo, bar]).then(responses => arr1[3] = 7);

setTimeout(() => {
    console.log(arr);
}, 3000);

Original Thread

By anonymous    2018-04-02

Have a look at https://stackoverflow.com/a/36727148/1823841 & [What is the event loop anyway?](https://www.youtube.com/watch?v=8aGhZQkoFbQ)

Original Thread

Popular Videos 1834

Submit Your Video

If you have some great dev videos to share, please fill out this form.