Music-R is available for use here
Over the past week, I've dug into my first real vanilla Javascript application, and it's been a really enjoyable week (surprisingly? maybe so)! For the last three weeks I have moaned and groaned over the growing pains of switching from Ruby to learning JS, but putting the skills I've learned to use on a real application has really changed my entire mindset about Javascript!
My application is a simple music recommender. You enter a song and its artist, and it spits out a related song. You have the option to make a username for yourself and keep track of recommended songs that you like. Pretty simple, but the whole thing ended up being about 300 lines of code! WHEW.
I used three API's for this project, the last.fm API, the Youtube API, and a my Rails backend API where I stored user and song data.
I had a good time playing around with CSS styling and DOM manipulation with this one-- it's probably the cutest looking application I've made so far. But more than that, I had a really good time building out the logic of my fetch requests.
The last.fm API has a built in endpoint that returns 100 related tracks when given a single track-- it's the first place that the app hooks into when a user enters a song. But, it leaves a lot to be desired. Last.fm doesn't have related songs for everything-- in fact, most of the music that I listen to at least, didn't have related tracks. So instead of throwing an alert or an error, I decided to construct a fallback for when the related tracks endpoint comes up empty. I built out some functions that would grab the artist of the song, feed it into the related artists last.fm endpoint, grab that artist's most popular songs, and return a random song from that list.
static getRelatedArtists(artistName) {
return fetch(`https://ws.audioscrobbler.com/2.0/?method=artist.getsimilar&artist=${artistName.toLowerCase().trim()}&api_key=efeaa32576655308d8b417be9812fc15&format=json`)
.then(function(response) {
return response.json();
})
.then(function(json) {
console.log(json)
let randomNum = Math.floor((Math.random() * 100))
let artist = json.similarartists.artist[randomNum].name
lastFmApi.getArtistTopSongs(artist)
})
.catch(function() {
alert("Something went wrong. Reload and try again!")
})
}
static getArtistTopSongs(artistName){
return fetch(`https://ws.audioscrobbler.com/2.0/?method=artist.gettoptracks&artist=${artistName.toLowerCase().trim()}&api_key=efeaa32576655308d8b417be9812fc15&format=json`)
.then(function(response) {
return response.json();
})
.then(function(json) {
console.log(json)
let randomNum = Math.floor((Math.random() * 50))
let song = json.toptracks.track[randomNum]
lastFmApi.displayResults(song)
console.log(song)
Youtube.getVideo(song.name, song.artist.name)
})
.catch(function() {
alert("Something went wrong. Reload and try again!")
})
}
I call it off the back of my fetch request to the related tracks fetch request in a simple if/else block that checks the length of the returned related tracks array. Once I implemented this, I almost never bumped up against a song without a recommendation.
All in all, this was a really great experience-- probably my favorite thing to have built! It might not be the most interesting in terms of user interactivity, but I definitely felt like the process of building this project was smoother than others, and I learned a TON. Happy listening!
Top comments (0)