dpDesignz
dpDesignz

Reputation: 1959

Using JQuery when and deferred returning undefined still

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();
}

Upvotes: 0

Views: 603

Answers (1)

Roamer-1888
Roamer-1888

Reputation: 19288

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.

Upvotes: 1

Related Questions