-1

I have this locations.json file where I store the titles, locations (lat, long), and phone numbers. The issue I'm facing right now might seem trivial to others but as a beginner I couldn't get it to work the way I like. I want to extract the ratings only from Yelp's api v3 and add it to the locations.rating array. The code I have below appends the whole response object return from Yelp, but when I tried to console.log (response.businesses[0].rating) it was able to print out only the rating. How do I make it return only the rating? Thanks in advance.

var yelpPhoneSearch = "https://api.yelp.com/v3/businesses/search/phone?phone=";
var cors_anywhere_url = 'https://cors-anywhere.herokuapp.com/';  // Yelp v3 api doesn't support CORS, need to use this 3rd party proxy service
var locations = [];
$.getJSON('/locations.json', function(data){
  for (var i = 0; i < data.length; i++) {
    var schools = {};
    schools.title = data[i].title;
    schools.location = data[i].location;
    schools.phone = data[i].phone;
    schools.rating = $.ajax({
      "async": true,
      "crossDomain": true,
      "url": cors_anywhere_url + yelpPhoneSearch + data[i].phone,
      "method": "GET",
      "headers": {
        "authorization": "Bearer " + yelpToken.access_token,
        "cache-control": "public, max-age=31536000",
      }
    }).done(function(response){
      // console.log(response);
      var rating = response.businesses[0].rating;
      return rating;
    });
    // Push all infos to locations array
    locations.push(schools);
  }
});
  • `it was able to print out only the rating. How do I make it return only the rating score?` how about an example of the data you receive ... what's the difference between `rating` and `rating score` – Jaromanda X Aug 15 '17 at 00:12
  • also, as AJAX (this included $.getJSON) is asynchronous, `schools.rating` will not be the value returned by `return rating;` it will be a jQuery promise of `response` (because you use .done) – Jaromanda X Aug 15 '17 at 00:14
  • If I run `console.log(JSON.stringify(locations[0].rating))` I get [this (pastebin. )](https://pastebin.com/WF5BbQZA) I'm not really familiar with jQuery promise, Is there any other way to push the yelp's rating into the locations array? – CryptoPsyche Aug 15 '17 at 00:38
  • I still can't see what you mean by "rating score" - that's `response.businesses[0].rating` as far as I can tell (4.5 in your pastebin) – Jaromanda X Aug 15 '17 at 00:50
  • Sorry for the confusion, I just meant rating. – CryptoPsyche Aug 15 '17 at 00:51

1 Answers1

0

using jQuery promises (which are almost like regular Promises except guaranteed to be available in old browsers) you can rewrite your code like so

var yelpPhoneSearch = "https://api.yelp.com/v3/businesses/search/phone?phone=";
var cors_anywhere_url = 'https://cors-anywhere.herokuapp.com/';  // Yelp v3 api doesn't support CORS, need to use this 3rd party proxy service

$.getJSON('/locations.json')
.then(function(data){
    return $.when.apply($, data.map(function(school) {
        return $.ajax({
            "async": true,
            "crossDomain": true,
            "url": cors_anywhere_url + yelpPhoneSearch + school.phone,
            "method": "GET",
            "headers": {
                "authorization": "Bearer " + yelpToken.access_token,
                "cache-control": "public, max-age=31536000",
            }
        }).then(function(response) {
            return {
                title: school.title,
                location: school.location,
                phone: school.phone,
                rating: response.businesses[0].rating
            };
        });
    }));
}).then(function() {
    var locations = [].slice.call(arguments);
    /* here locations is an array of 
    {
        title,
        location,
        phone,
        rating
    }
    */
});

Note: because of the asynchronous nature of $.ajax you can't access the array of results outside of the last .then because asynchronous code is asynchronous

For completeness - ES2015+ with native Promises, the code would be

$.getJSON('/locations.json').then(data => 
    Promise.all(data.map(school => 
        $.ajax({
            "async": true,
            "crossDomain": true,
            "url": cors_anywhere_url + yelpPhoneSearch + school.phone,
            "method": "GET",
            "headers": {
                "authorization": "Bearer " + yelpToken.access_token,
                "cache-control": "public, max-age=31536000",
            }
        }).then(response => ({
            title: school.title,
            location: school.location,
            phone: school.phone,
            rating: response.businesses[0].rating
        }))
    ))
).then(locations => {
    /* here locations is an array of 
    {
        title,
        location,
        phone,
        rating
    }
    */
});

If you need to access locations in some other parts of your code, and assuming the code in your question is not taken from a function (i.e. the vars are all global scoped)

var yelpPhoneSearch = "https://api.yelp.com/v3/businesses/search/phone?phone=";
var cors_anywhere_url = 'https://cors-anywhere.herokuapp.com/';  // Yelp v3 api doesn't support CORS, need to use this 3rd party proxy service

var locations = $.getJSON('/locations.json')
.then(function(data){
    return $.when.apply($, data.map(function(school) {
        return $.ajax({
            "async": true,
            "crossDomain": true,
            "url": cors_anywhere_url + yelpPhoneSearch + school.phone,
            "method": "GET",
            "headers": {
                "authorization": "Bearer " + yelpToken.access_token,
                "cache-control": "public, max-age=31536000",
            }
        }).then(function(response) {
            return {
                title: school.title,
                location: school.location,
                phone: school.phone,
                rating: response.businesses[0].rating
            };
        });
    }));
}).then(function() {
    return [].slice.call(arguments);
});

Now, in code where ever you need to use locations, you'll need to get access to the result using typical Promise methodology

locations.then(function(value) {
    // in here,  value is an array of locations
});

Without seeing how you are using locations in your actual code, this may not be as easy as above, because, once you deal with asynchronous code, you need to deal with it properly

Jaromanda X
  • 47,382
  • 4
  • 58
  • 76
  • I tried your code but now the locations array is empty. – CryptoPsyche Aug 15 '17 at 01:25
  • well that's unfortunate - did you try to work with `locations` outside of the last .then or where I said `here locations is an array of`? when you say it's empty, do you mean it's length is zero? – Jaromanda X Aug 15 '17 at 01:27
  • The locations array is just used to created markers on Google Map. I just `console.log(locations)` at the global scope (not inside the `then` block) and its length is zero. Using my code the locations array has 24 objects. – CryptoPsyche Aug 15 '17 at 01:37
  • right ... but **where** do you do this, inside the `.then` as I said you SHOULD, or outside it. because you get the rating asynchronously after getting the list of locations asynchronously, you can't synchronously access locations array outside the asynchronous code - that's how asynchronous code works – Jaromanda X Aug 15 '17 at 01:40
  • if you `console.log(locations)` just after `locations = [].slice ...` and it is zero length, that would suggest that `data` is zero length and that there were no requests made to `cors_anywhere_url` – Jaromanda X Aug 15 '17 at 01:42
  • note that I specifically used `var locations =` inside the last `.then` callback, to emphasise the scope of the results – Jaromanda X Aug 15 '17 at 01:43
  • You are correct, yelp's ratings were successfully pushed to the locations array. But the whole thing now would break my app, because `locations` is no longer a global variable which the app was depending on. How do I make it global again? Please tell. – CryptoPsyche Aug 15 '17 at 02:06
  • you can't work with asynchronous results (locations in your case) in a synchronous way - let me edit the answer and show you how you may be able to mitigate the amount of code you need to change - though, without seeing how you use locations I'm only guessing – Jaromanda X Aug 15 '17 at 02:09
  • I've figured it out, using your advice. Now I had to move some of my code inside the `then` statement. This is my first time learning about Promises in JS. Thank you very much. I still need to study the code you wrote, some syntax I still haven't learned. – CryptoPsyche Aug 15 '17 at 04:52