Lucia Pasarin
Lucia Pasarin

Reputation: 2308

Calling REST endpoint from Javascript

I am trying to call Spotify API from Javascript like this:

function callAPI() {
    var xhttp = new XMLHttpRequest();
    xhttp.open('GET', 'https://api.spotify.com/v1/search?q=Muse&type=track');
    xhttp.setRequestHeader('Content-Type', 'application/json');
    xhttp.setRequestHeader('Authorization', 'Bearer <MY_ACCESS_TOKEN>');
    xhttp.send();
    var response = JSON.parse(xhttp.responseText);
}

However, xhttp.responseText is empty, although the request returns 200.

I can see in the browser that the request is returning the expected result but somehow I cannot extract it from the Javascript: enter image description here

I tried calling the REST endpoint using Java (since I am more familiar with it) and that worked:

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.net.HttpURLConnection;
import java.net.URL;

public class Test {
    public static void main(String[] args) {
        System.out.println("blah");

        URL url = null;
        try {
            url = new URL("https://api.spotify.com/v1/search?q=Muse&type=track");
            HttpURLConnection connection = (HttpURLConnection) url.openConnection();
            connection.setRequestMethod("GET");
            connection.setRequestProperty("Authorization", "Bearer <MY_ACCESS_TOKEN>");
            String responseMessage = connection.getResponseMessage();
            BufferedReader reader = new BufferedReader(new InputStreamReader(connection.getInputStream()));
            StringBuffer content = new StringBuffer();

            try (reader) {
                String line;

                while ((line = reader.readLine()) != null) {
                    content.append(line);
                }
            } finally {
                reader.close();
            }
            System.out.println("Response: " + responseMessage);
            System.out.println("Content: " + content.toString());
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

}

I am a Javascript newbie, so what am I doing wrong? Thanks a lot in advance!

Upvotes: 1

Views: 19577

Answers (4)

Lucia Pasarin
Lucia Pasarin

Reputation: 2308

Thanks a lot everybody for your replies and thanks for reminding me of asynchronicity in Javascript, which I had totally forgotten about. I managed to make this work by using axios library, which I read integrates nicely with Vue.js, which I am intending to use. Here is the solution that worked for me:

<script>
import axios from "axios";
export default {
  name: 'HelloWorld',
  data () {
    return {
      msg: ''
    }
  },
  mounted() {
    axios({method: "GET", "url": "https://api.spotify.com/v1/search?q=Muse&type=track"}).then(result => {
      this.msg = result.data.tracks.items[0].name
  }, error => {
    console.error(error);
  });
  }
}
</script>

Upvotes: 1

D0ubleGunz
D0ubleGunz

Reputation: 58

I take it from your original post, that you're more familiar with Java, and so in your Javascript code, var response = JSON.parse(xhttp.responseText); your expecting the response text to be available to parse. In Java, the code works because the request is sent and the remaining operations are blocked until there is a response. Javascript doesn't follow the same paradigm, it doesn't wait for a response, and attempts to parse xhttp.responseText before anything has been returned from the request.

The documentation explains this XMLHttpRequest.responseText

While handling an asynchronous request, the value of responseText always has the current content received from the server, even if it's incomplete because the data has not been completely received yet.

You know the entire content has been received when the value of readyState becomes XMLHttpRequest.DONE (4), and status becomes 200 ("OK").

Because Javascript will doesn't wait for the response, your code must wait for an event to signal that the response has been made. This is the asynchronous behavior that the others posters are referring to. The documentation here describes how to create the code that will listen for the response event. The answer submitted by Boo Berr'ita is a good example, using your code.

Upvotes: 2

Georgy Bunin
Georgy Bunin

Reputation: 46

You can add event handler on "load":

function onXHRLoad() {
  console.log(this.responseText);
}

function callAPI() {
    var xhttp = new XMLHttpRequest();
    xhttp.open('GET', 'https://api.spotify.com/v1/search?q=Muse&type=track');
    xhttp.setRequestHeader('Content-Type', 'application/json');
    xhttp.setRequestHeader('Authorization', 'Bearer <MY_ACCESS_TOKEN>');
    xhttp.addEventListener('load', onXHRLoad);
    xhttp.send();
}

Upvotes: 1

Bourbia Brahim
Bourbia Brahim

Reputation: 14712

you forget the onreadystatechange callback function :

just wrap the result inside this fonction :

  xhttp.onreadystatechange = function() {
    if (this.readyState == 4 && this.status == 200) {
      var response = JSON.parse(this.responseText);
    }
  };

Upvotes: 1

Related Questions