javascript - 使用 JQuery when 和 deferred 仍然返回未定义

标签 javascript jquery-deferred .when

我刚开始使用 $.when$.Deferred(),但我似乎无法让它们工作

我想做的是运行一些函数,当它们全部完成时触发最终函数

这是我尝试过的几个选项

选项 1 - 返回 d1.getRating 不是一个函数(这是脚本中进一步的函数),遵循 JQuery 中的文档据我了解他们

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

选项 2 - 返回 ratingValue 未定义

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

任何建议或正确方向的插入将不胜感激

完整源代码可以是viewed on GitHub

更新

读完JQuery docs后我意识到再次说明 resolve() 不是通用函数的名称,因此我修改了代码,但仍然得到 ratingValue is undefined 返回

更新了选项 1 代码

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

更新2

抱歉,很抱歉没有包含 getRating 函数。如下

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

最佳答案

主要要做的是编写getRating()来返回一个promise。您可以promisify XMLHttpRequest(),但使用jQuery.ajax()要容易得多。

这就是,基于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.
    });
}

然后,在主例程中也使用 jQuery.ajax() :

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

请注意,由于 jQuery.ajax() 返回一个 Promise,因此无需生成/解析您自己的 jQuery.Deferred()

上面的代码可能不是 100% 正确,但离工作解决方案应该还有很大的距离。

关于javascript - 使用 JQuery when 和 deferred 仍然返回未定义,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/38940881/

相关文章:

javascript - 如何在彩色 Canvas 上书写文本(JavaScript 新手)

javascript - 如何使用一种形式获取动态文本

javascript - 对函数调用进行排序

javascript - OOP 和 jQuery : how to init a var with Deferred();

javascript - "unresolving"延迟对象

jquery - 有条件地添加到 jQuery .when

javascript - then 中的函数在 when 结束之前被调用

javascript - sequelize 是否有任何更改跟踪内置机制?

javascript - Clipboard.js,其中所需复制的文本 div 将与页面上的其他 div 具有相同的类或 id

jQuery 延迟对象被调用两次