Dustin Wortmann
Dustin Wortmann

Reputation: 33

Node.js execution doesn't continue after function in if-statement

This snippet of code gets executed until the end of the getRefreshToken function is at its last line. The play_song function does not get triggered. Am I misunderstanding the way JS works? For now I have included the call to play_song at the end of the getRefreshToken function, and of course that works as expected. However, I am very confused why it doesn't just execute function after function in the if-statement.

function checkTime () {
 var now = new Date();
 if (now.getHours() == time[0] && now.getMinutes() == time[1]) { 
  getRefreshToken();
  play_song();
 }
}

The contents of getRefreshToken:

 function getRefreshToken() {
  console.log('Starting token request')
  // requesting access token from refresh token
  var refresh_token = tokens.refresh;
  var authOptions = {
    url: 'https://accounts.spotify.com/api/token',
    headers: { 'Authorization': 'Basic ' + (new Buffer(client_id + ':' + client_secret).toString('base64')) },
    form: {
      grant_type: 'refresh_token',
      refresh_token: refresh_token
    },
    json: true
  };
  request.post(authOptions, function(error, response, body) {
    if (!error && response.statusCode === 200) {
      tokens.access = body.access_token;
    }
    //play_song(); //only a temporary fix
  })
}

Upvotes: 2

Views: 834

Answers (1)

Tom
Tom

Reputation: 1686

Yes in JavaScript, functions are not necessarily synchronous as you might be familiar with in other programming languages. JavaScript is single threaded, however operations such as fetching data, querying API's, databases, I/O etc. all happen in parallel to the main execution of your code.

I assume getRefreshToken() is making some sort of network request and the fact you mentioned play_song works when put at the end of getRefreshToken() gives it away.

There are many ways to deal with this in JavaScript, here's a good resource.

Here's an example for your situation, I removed some unneeded code for the purpose of the example:

// Using callbacks
function checkTime() {
  getRefreshToken(play_song);
}

function getRefreshToken(callback) {
  request.post(authOptions, function(error, response, body) {
    if (!error && response.statusCode === 200) {
      tokens.access = body.access_token;
    }
    callback();
  })
}

// Using Promises
function checkTime() {
  getRefreshToken()
    .then(() => {
      play_song();
    })
}

function getRefreshToken(callback) {
  return new Promise((resolve, reject) => {
    request.post(authOptions, function(error, response, body) {
      if (!error && response.statusCode === 200) {
        tokens.access = body.access_token;
      }
      resolve();
    })
  })
}

// Using Async/Await
async function checkTime() {
  await getRefreshToken()
  play_song();
}

function getRefreshToken(callback) {
  return new Promise((resolve, reject) => {
    request.post(authOptions, function(error, response, body) {
      if (!error && response.statusCode === 200) {
        tokens.access = body.access_token;
      }
      resolve();
    })
  })
}

Upvotes: 2

Related Questions