【问题标题】:Asynchronous Problems with Javascript Hacker News APIJavascript Hacker News API 的异步问题
【发布时间】:2014-11-16 20:09:50
【问题描述】:

Hacker News 最近发布了一个API,我用它来显示 Hacker News 当前排名前十的项目。我遇到了一些问题。

当我运行下面的代码时,首页项目的顺序不准确,从首页的第二个跳转到第四个,到第一个,到第五个,到第三个等等。再次运行代码会导致再次略有不同的顺序。

$.getJSON('https://hacker-news.firebaseio.com/v0/topstories.json', function(json) {
    var convoText = '<ol>';
    for (var i = 0; i < 10; i++) {
        (function(i) {
            $.getJSON('https://hacker-news.firebaseio.com/v0/item/' + json[i] + '.json', function(json2) {
                convoText += '<li><a href="' + json2.url + '">' + json2.title + '</a></li>';
                if (i === 9) {
                    convoText += '</ol>';
                    addConvo(convoText);
                }
            });
        })(i);
    }
});

我知道这是 Javascript 的异步特性造成的。我该如何解决?

【问题讨论】:

    标签: javascript jquery ajax asynchronous


    【解决方案1】:

    诀窍是在循环中同步创建和附加一个&lt;li&gt;&lt;a&gt;&lt;/a&gt;&lt;/li&gt; 结构 - 从而建立正确的顺序 - 然后在它到达时用json2 数据异步填充它。

    $.getJSON('https://hacker-news.firebaseio.com/v0/topstories.json', function(json) {
        var $ol = $('<ol/>').appendTo(...);//wherever
        for (var i = 0; i < Math.min(json.length, 10); i++) {
            (function(i) {
                var $a = $('<li><a></a></li>').appendTo($ol).find('a');
                $.getJSON('https://hacker-news.firebaseio.com/v0/item/' + json[i] + '.json', function(json2) {
                    $a.attr('href', json2.url).text(json2.title);
                });
            })(i);
        }
    });
    

    您必须填写.appendTo(...) 行。从&lt;ol&gt;...&lt;/ol&gt; 附加的问题中我不知道。

    【讨论】:

    • 赞成唯一不等到所有请求都完成后才显示列表项的解决方案。
    • @DanielKopitchinski,一个天才,我爱你!
    • 还没有人提到Math.min(json.length, 10)
    【解决方案2】:

    您可以为此使用 jQueries $.when:

      $.getJSON('https://hacker-news.firebaseio.com/v0/topstories.json', function(json) {
        var requests = [];
    
        for (var i = 0; i < 10; i++) {
          requests.push($.getJSON('https://hacker-news.firebaseio.com/v0/item/' + json[i] + '.json'));
        }
    
        $.when.apply($, requests).done(function() {
          var results = [].slice.call(arguments);
          var list = results.map(function(arr) {
            return '<li><a href="' + arr[0].url + '">' + arr[0].title + '</a></li>';
          });
          var convoText = '<ol>' + list.join('') + '</ol>';
          console.log(convoText);
        });
      });
    

    【讨论】:

    • 您能详细说明一下吗?我对 jQuery 比较陌生。
    • 添加了一个完整的示例
    • 谢谢!完美运行!
    【解决方案3】:

    有几种方法可以解决此问题。最简单的方法是,不要追加到convoText,而是使用数组,并在获取数据时设置其索引。喜欢data[i] = json2;。然后当你所有的数据都被获取后,加入你的数组。

    一个更具结构性的解决方法是将循环重新架构为一组承诺,并在它们全部解决后构建您的 HTML(@xat 上面提到的内容)。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2010-12-14
      相关资源
      最近更新 更多