0

I'm new to using $.when and $.Deferred(), and I can't seem to get them to work

What I'm trying to do is run a few functions, and when they've all finished trigger a final function

Here are a couple of options I've tried

Option 1 - Returning d1.getRating is not a function (this is a function further up in the script) following docs from JQuery as I understood them

// Set Deferred
var d1 = $.Deferred();
// Return movie information
if (idResp[0].type === "movie") {
  // Output Slug
  traktSlug = 'movies/' + idResp[0].movie.ids.slug;
  // Output
  $.when(d1).done(function (ratingValue) {
      console.log('Rating Is: ' + ratingValue);
      outputIMDb(showCheckIn, traktSlug, ratingValue);
  });
  // Get Rating
  d1.getRating(idResp[0].type, idResp[0].movie.ids.trakt);
}

Option 2 - Returning ratingValue is undefined

// Return movie information
if (idResp[0].type === "movie") {
  // Output Slug
  traktSlug = 'movies/' + idResp[0].movie.ids.slug;
  // Output
  $.when(getRating(idResp[0].type, idResp[0].movie.ids.trakt)).done(function (ratingValue) {
      console.log('Rating Is: ' + ratingValue);
      outputIMDb(showCheckIn, traktSlug, ratingValue);
  });
}

Any suggestions or a nudge in the right direction would be much appreciated

Full source code can be viewed on GitHub

UPDATE

I realised after reading the JQuery docs again that resolve() is not the name of a generic function, so I modified my code, but I'm still getting ratingValue is undefined back

Updated Option 1 Code

// Set Deferred
var d1 = $.Deferred();
// Return movie information
if (idResp[0].type === "movie") {
  // Output Slug
  var traktSlug = 'movies/' + idResp[0].movie.ids.slug;
  // Output Div
  $.when(d1).done(function(ratingValue) {
      console.log('Rating Is: ' + ratingValue);
      outputIMDb(1, traktSlug, ratingValue);
  });
  // Get Rating
  d1.resolve(getRating(idResp[0].type, idResp[0].movie.ids.trakt));
}

UPDATE 2

Sorry, my apologies for not including the getRating function. As follows

// Get Rating
function getRating(type, id, season = 0, episode =0) {
    var slugType = "";
    switch (type) {
        case "movie":
            slugType = "movies";
            break;
        default:
            slugType = "movies";
            break;
    }
    var request = new XMLHttpRequest();
    request.open('GET', 'https://api.trakt.tv/' + slugType + '/' + id + '/ratings');
    request.setRequestHeader('Content-Type', 'application/json');
    request.setRequestHeader('trakt-api-version', '2');
    request.setRequestHeader('trakt-api-key', APP_KEY);
    request.onreadystatechange = function () {
        if (this.readyState === 4) {
            // Get Response and put in array
            var ratingsResp = JSON.parse(this.responseText);
            // Return Rating
            return Math.round(ratingsResp.rating * 10);
        } else {
            return 0;
        }
      };
      request.send();
}
25
  • I'm pretty sure you don't want to post your private API keys on github. Commented Aug 14, 2016 at 10:04
  • @Tomalak I'm new to github. How can I sync my code up without posting them? :-/ Commented Aug 14, 2016 at 10:06
  • That being said, why do you use write XMLHttpRequest() code when you have jQuery? That doesn't make any sense at all. Use the jQuery Ajax functions. Commented Aug 14, 2016 at 10:06
  • @Tomalak that's the requirements by the API I'm using Commented Aug 14, 2016 at 10:08
  • The first thing to do is to delete your repo and reset your API keys. Then research how to do that. Articles have been written about that, you'll find a way. Commented Aug 14, 2016 at 10:08

1 Answer 1

1

The main thing to do is to write getRating() to return a promise. You could promisify XMLHttpRequest() but it's much easier to use jQuery.ajax().

Here it is, based on the original code on GitHub :

function getRating(type, id, season=0, episode=0) { // mmm, formal defaults - odd for browser-based javascript.
    var slugType;
    switch(type) {
        case 'movie':
            slugType = 'movies';
        break;
        default:
            slugType = 'movies';
    }
    return $.ajax({
        url: 'https://api.trakt.tv/' + slugType + '/' + id + '/ratings',
        headers: {
            'Content-Type': 'application/json',
            'trakt-api-version': '2',
            'trakt-api-key': APP_KEY
        },
        dataType: 'json'
    }).then(function(response) {
        return Math.round(response.rating * 10);
    }).then(null, function(xhr, textMessage, errorThrown) {
        console.error('getRating error: ', textMessage);
        return $.when(0); // error recovery.
    });
}

Then, use jQuery.ajax() in the main routine too :

chrome.storage.local.get('access_token', function(result) {
    var ACC_TOK = result.access_token;
    if (ACC_TOK && typeof ACC_TOK !== undefined) {
        if (tabURL.includes('imdb.com')) {
            $.ajax({
                url: 'https://api.trakt.tv/search/imdb/' + tabURL.match(/tt\d{7}/),
                headers: {
                    'Content-Type': 'application/json',
                    'trakt-api-version': '2',
                    'trakt-api-key': APP_KEY
                },
                dataType: 'json'
            }).then(function(idResp) {
                if(idResp[0].type === 'movie') {
                    return getRating(idResp[0].type, idResp[0].movie.ids.trakt).then(function(ratingValue) {
                        console.log('Rating Is: ' + ratingValue);
                        outputIMDb(1, 'movies/' + idResp[0].movie.ids.slug, ratingValue);
                    });
                } else {
                    console.log("Type: " + idResp.type);
                }
            }).fail(function(xhr, textMessage, errorThrown) {
                console.error(textMessage);
            });
        }
    }
});

Note that because jQuery.ajax() returns a promise, there's no need to generate/resolve your own jQuery.Deferred()s.

Code above may not be 100% correct but should go a considerable distance to a working solution.

Sign up to request clarification or add additional context in comments.

3 Comments

Thanks heaps! I'll review this code tonight and see how I go. Much appreciate the help :-)
Are you purposely using ES6 constructs (default parameters) for browser-based code? If so, you should probably explain that so the OP (who is somewhat of a beginner) does not get confused with that or isn't surprised when it doesn't work in some browsers.
@jfriend00, just repeating OP's own code, in that respect, despite its apparent absurdity.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.