I'm trying to use d3.json()
inside of a function to return data Spotify's API given an artist ID (such as 5K4W6rqBFWDnAN6FQUkS6x), but I can't figure out how to effectively return the data. The function looks like
// Get artist's related artist's information
function relatedArtists(id){
var jsonPromise = new Promise(function(resolve, reject) {
// Async JSON request
d3.json('https://api.spotify.com/v1/artists/' + id + '/related-artists', function(error, data){
if(error) reject(error);
resolve(data.artists);
});
});
jsonPromise.then(function(success) {
console.log(success);
//return(success) //doesn't work
});
jsonPromise.catch(function(error){
console.error(error);
});
}
I've tried creating a variable within the function and then modifying it
function relatedArtists(id){
var testVar = 'hello';
var jsonPromise = new Promise(...{
// Async JSON request
d3.json(...)
});
jsonPromise.then(function(success) {
testVar = success;
});
return(testVar);
}
But testVar
remains 'hello'
, despite my best efforts. I've done some reading about scope and promises, but am happy to do more if there's some core mechanic of either that I'm not understanding. Thanks for reading!
The response will never be available in your calling code due to asynchronous nature of requests. You can use Promises (as supposed by Alexander T. and you, good choice in many cases!) but d3.queue
does a good job, too. In my snippet you can see how to run code with the results of multiple requests.
function buildRelatedArtistUri(id) {
return 'https://api.spotify.com/v1/artists/' + id + '/related-artists';
}
d3.queue()
.defer(d3.json, buildRelatedArtistUri('5K4W6rqBFWDnAN6FQUkS6x'))
.await(function(error, data) {
// data and data.artists are available in this function‘s scope only
console.log(data.artists);
});
d3.queue()
.defer(d3.json, buildRelatedArtistUri('5K4W6rqBFWDnAN6FQUkS6x'))
.defer(d3.json, buildRelatedArtistUri('3nFkdlSjzX9mRTtwJOzDYB'))
.await(function(error, data1, data2) {
// this function will be called once both functions have finished
console.log(data1.artists, data2.artists);
});
<script src="https://d3js.org/d3.v4.min.js"></script>
You can return Promise
and use relatedArtists
function like so
function relatedArtists(id) {
return new Promise(function(resolve, reject) {
d3.json('https://api.spotify.com/v1/artists/' + id + '/related-artists', function(error, data) {
if (error) {
reject(error);
} else {
resolve(data.artists);
}
});
});
}
relatedArtists('5K4W6rqBFWDnAN6FQUkS6x')
.then(function (data) {
console.log(data);
})
.catch(function (error) {
console.log(error);
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/3.4.11/d3.min.js"></script>
In this case, you can not assign the value to testVar
, because d3.json
is the asynchronous method and that means that d3.json
can be done after code execution.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With