Reputation: 2308
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:
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
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
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
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
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