Joseph
Joseph

Reputation: 339

JavaScript callback running out of order in Chrome?

I am trying to call a function AFTER another function has completed. Normally, this is done with callbacks, at least with Node.js. However, when I try to run the following code in Chrome, the callback function seems to execute before the main function. Am I writing my function/callback wrong? Shouldn't the second function (the callback function) only execute after the first one is complete?

If callbacks don't work when the javascript is running client-side in the browser, is there another way I can ensure the second function runs only when the first function is complete?

<html>
<head></head>
<body>
<script>

function firstLoad(callback) {
  console.log("firstLoad function fired.");
}

function secondLoad() {
  console.log("secondLoad function fired.");
}

firstLoad(secondLoad());

</script>
</body>
</html>

In Chrome Developer Tools Console, the above code gives me:

secondLoad function fired.

firstLoad function fired.

I would expect it to be the other way around.

Upvotes: 0

Views: 554

Answers (2)

brein
brein

Reputation: 1419

I'm trying to give a simpler answer here that gets straight to the point, I have edited your code so it's working the way you are expecting it to work and added some comments to explain what's happening:

<html>
  <head></head>
  <body>
  <script>

    function firstLoad(callback) { //secondLoad is "saved" in the callback variable
      console.log("firstLoad function fired.");

      //When Firstload is done with doing all it has to do you have to manually call 
      //the callback which references to the secondLoad function:
      callback();
    }

    function secondLoad() {
      console.log("secondLoad function fired.");
    }

    //Here you pass the secondLoad function as a parameter for the firstLoad function,
    //in your code you were passing the *result* of secondLoad
    firstLoad(secondLoad); 

  </script>
  </body>
</html>

I am assuming that firstLoad is not doing asynchronous stuff like network requests

Upvotes: 2

CertainPerformance
CertainPerformance

Reputation: 370819

Expressions in an argument list are evaluated immediately, so that the expression can be passed to the function. So with

firstLoad(secondLoad());

secondLoad is called and evaluated to

firstLoad(undefined);

before firstLoad is called.

If firstLoad is asynchronous, pass just the secondLoad function name instead, and call it as a callback at the end of the asynchronous action:

function firstLoad(callback) {
  console.log("firstLoad function fired.");
  setTimeout(() => {
    console.log('firstload done');
    callback();
  }, 1000);
}

function secondLoad() {
  console.log("secondLoad function fired.");
}

firstLoad(secondLoad);

You can also have firstLoad return a Promise:

function firstLoad() {
  console.log("firstLoad function fired.");
  return new Promise((resolve) => {
    setTimeout(() => {
      console.log('firstload done');
      resolve();
    }, 1000);
  });
}

function secondLoad() {
  console.log("secondLoad function fired.");
}

firstLoad()
  .then(secondLoad);

Of course, if firstLoad isn't asynchronous, just call secondLoad after firstLoad:

function firstLoad(callback) {
  console.log("firstLoad function fired.");
}

function secondLoad() {
  console.log("secondLoad function fired.");
}

firstLoad();
secondLoad();

Upvotes: 1

Related Questions