如何使用 .ajax 查询多个 GitHub url,然后对结果进行排序?

How to use .ajax to query multiple GitHub urls and then sort the result?

我尝试使用 jQuery 编写一个 Javascript 来检索我用户名下的存储库和我在 GitHub 上拥有的组织,然后按观察者数量和很快。然而,我从来没有真正让它工作——尽管为 github 设置了 AUTH-TOKEN 以防止最大速率限制。核心任务只是查询多个 url 并在我可以做的排序和格式化之前合并原始数据。我在网上搜索过,但是检索多个数据集并将它们组合起来似乎很棘手,因为我可能不了解变量和数据结构的范围。

我的 Javascript 在 the fiddle 上。谁能指导我连接多个查询并对结果进行排序?你可以给我一些简单的例子。下面是 javascript 代码和 html 部分。我留下了一些注释代码来展示我尝试过的另一种方式。

(function ($, undefined) {
      $.ajaxSetup({ cache: false });
      // Put custom repo URL's in this object, keyed by repo name.
      var repoUrls = {
      };
      // Put custom repo descriptions in this object, keyed by repo name.
      var repoDescriptions = {
      };
      var repos = [];

      function repoUrl(repo) {
        return repoUrls[repo.name] || repo.html_url;
      }
      function repoDescription(repo) {
        return repoDescriptions[repo.name] || repo.description;
      }

      function addRecentlyUpdatedRepo(repo) {
        var $item = $("<li>");

        var $name = $("<a>").attr("href", repo.html_url).text(repo.name);
        $item.append($("<span>").addClass("name").append($name));

        var $time = $("<a>").attr("href", repo.html_url + "/commits").text(strftime("%h %e, %Y", repo.pushed_at));
        $item.append($("<span>").addClass("time").append($time));

        $item.append('<span class="bullet">&sdot;</span>');

        var $open_issues = $("<a>").attr("href", repo.html_url + "/open_issues").text(repo.open_issues + " open_issues");
        $item.append($("<span>").addClass("open_issues").append($open_issues));

        var $watchers = $("<a>").attr("href", repo.html_url + "/watchers").text(repo.watchers + " watchers");
        $item.append($("<span>").addClass("watchers").append($watchers));

        $item.append('<span class="bullet">&sdot;</span>');

        var $forks = $("<a>").attr("href", repo.html_url + "/network").text(repo.forks + " forks");
        $item.append($("<span>").addClass("forks").append($forks));

        $item.appendTo("#recently-updated-repos");
      }

      function addRepo(repo) {
        var $item = $("<li>").addClass("repo rep " + (repo.language || '').toLowerCase());
        var $link = $("<a>").attr("href", repoUrl(repo)).appendTo($item);
        $link.append($("<h2>").text(repo.name));
        // $link.append($("<h3>").text(repo.watchers + " watchers" + " / " + repo.open_issues + " open issues"));
        $link.append($("<p style='line-height:1em;'>").text(repoDescription(repo)));
        //$link.append($("<p style='line-height:1em;'>").text("Updated " +
        //  strftime("%h %e, %Y", repo.pushed_at)));
        $link.append($("<h3 style='top:23px; right:1px;'>").addClass("language").text(repo.language));

        $item.appendTo("#repos");
      }
      //var tokenkey='xxx';
      function queryorgrepo(requrl){
      //return $.ajax({
      $.ajax({
         url: requrl,
         async: false,
         dataType: 'json',
         //headers: 'Authorization: token '+tokenkey,
         success: function (result) {
         //temprepos = result.data;
         $.merge(repos, result.data);
         //$.merge(temprepos, result.data);
         //repos += result.data;
         //console.log(repos);
         }
      });
      return repos;
      console.log(repos);
      };
      
      var orgnames = ['CQuIC', 
                      'JuliaCN', 
                      'JuliaQuantum', 
                      'ICIQ'];
      //var indx = 0;
      var orgurls = [];
      //var results=[];
      for (var indx = 0; indx < orgnames.length; indx++){
        orgurls[indx] = "https://api.github.com/orgs/"+orgnames[indx]+"/repos?per_page=100&callback=?";
      };
      //alert(orgurls);
      for (var indx = 0; indx < orgurls.length; indx++){
        //repos=$.merge(repos,queryorgrepo(orgurls[indx]));
        queryorgrepo(orgurls[indx]);
        //temprepos.push(queryorgrepo(orgurls[indx]));
        //results.push(queryorgrepo(orgurls[indx]));
        console.log(repos);
       }
      //alert(tokenkey);
      //alert(repos);
      // invoke each function stored in the result array and proceed when they are all done
      //$.when.apply(this, repos).done(function () {
      // merge the arrays
      //for (var i = 0; i < temprepos.length; i++) {
      //  $.merge(repos, temprepos[i]);
      //};
      //  console.log(repos);
      //});
      //testrepos=queryorgrepo("https://api.github.com/orgs/CQuIC/repos?per_page=100&callback=?");
      //alert(repos);
      // Add organization repos.
      $.ajax({
         url: 'https://api.github.com/users/i2000s/repos?per_page=100&callback=?',
         async: false,
         dataType: 'json',
         //headers: 'Authorization: token '+tokenkey,
         success: function (result){
          //repos += result.data;
          $.merge(repos,result.data);
          $(function () {
          $("#num-repos").text(repos.length);

          // Convert pushed_at to Date.
          $.each(repos, function (i, repo) {
            repo.pushed_at = new Date(repo.pushed_at);

            var weekHalfLife  = 1.146 * Math.pow(10, -9);

            var pushDelta    = (new Date) - Date.parse(repo.pushed_at);
            var createdDelta = (new Date) - Date.parse(repo.created_at);

            var weightForPush = 1;
            var weightForWatchers = 1.314 * Math.pow(10, 7);

            repo.hotness = weightForPush * Math.pow(Math.E, -1 * weekHalfLife * pushDelta);
            repo.hotness += weightForWatchers * repo.watchers / createdDelta;
          });

          // Sort by highest # of watchers.
          repos.sort(function (a, b) {
            if (a.hotness < b.hotness) return 1;
            if (b.hotness < a.hotness) return -1;
            return 0;
          });
          // Only first 12 hotest repos are shown.
          $.each(repos.slice(0,12), function (i, repo) {
            addRepo(repo);
          });

          // Sort by most-recently pushed to.
          repos.sort(function (a, b) {
            if (a.pushed_at < b.pushed_at) return 1;
            if (b.pushed_at < a.pushed_at) return -1;
            return 0;
          });

          $.each(repos.slice(0, 3), function (i, repo) {
            addRecentlyUpdatedRepo(repo);
          });
        });
        
      }});
      
     

    })(jQuery);
<div class="row">
    <h2 align="center">Sharing code repositories</h2>
    <div id="wrapper" class="grid clearfix">
      <div id="main" class="grid-1">
        <div><h2>Xiaodong Qi's Open-source Repositories</h2></div>
        <h4> This is some sample text here.</h4>
      </div>

      <div class="grid grid-3">
        <div id="statistics" class="grid-1 alpha header">
          <h1 style="margin: 5px 5px 0;">Statistics</h1>
          <p style="margin: 5px 5px 0px;"> <a href="https://github.com/i2000s/repositories"><span id="num-repos">&nbsp;</span> public repos</a> </p>
          <p style="margin: 5px 5px 0px;"><a href="https://github.com/i2000s">https://github.com/i2000s</a></p>
        </div>

        <div id="recently-updated" class="grid-2 omega header">
          <h1 style="margin: 5px 5px 0;">Recently updated <a href="https://github.com/i2000s/repositories">View All on GitHub</a></h1>
          <ol id="recently-updated-repos" style="margin-left: -15px; margin-top: 15px"></ol>
        </div>
      </div>

        <ol id="repos"></ol>
    </div>
  </div>

谢谢。

我已经在 Jake 的帮助下弄明白了。诀窍是使用 $.when.apply().done() 结构。所以,我有以下修改代码:

(function ($, undefined) {
      $.ajaxSetup({ cache: false });
      // Put custom repo URL's in this object, keyed by repo name.
      var repoUrls = {
      };
      // Put custom repo descriptions in this object, keyed by repo name.
      var repoDescriptions = {
      };
      var repos = [];

      function repoUrl(repo) {
        return repoUrls[repo.name] || repo.html_url;
      }
      function repoDescription(repo) {
        return repoDescriptions[repo.name] || repo.description;
      }

      function addRecentlyUpdatedRepo(repo) {
        var $item = $("<li>");

        var $name = $("<a>").attr("href", repo.html_url).text(repo.name);
        $item.append($("<span>").addClass("name").append($name));

        var $time = $("<a>").attr("href", repo.html_url + "/commits").text(strftime("%h %e, %Y", repo.pushed_at));
        $item.append($("<span>").addClass("time").append($time));

        $item.append('<span class="bullet">&sdot;</span>');

        var $open_issues = $("<a>").attr("href", repo.html_url + "/open_issues").text(repo.open_issues + " open_issues");
        $item.append($("<span>").addClass("open_issues").append($open_issues));

        var $watchers = $("<a>").attr("href", repo.html_url + "/watchers").text(repo.watchers + " watchers");
        $item.append($("<span>").addClass("watchers").append($watchers));

        $item.append('<span class="bullet">&sdot;</span>');

        var $forks = $("<a>").attr("href", repo.html_url + "/network").text(repo.forks + " forks");
        $item.append($("<span>").addClass("forks").append($forks));

        $item.appendTo("#recently-updated-repos");
      }

      function addRepo(repo) {
        var $item = $("<li>").addClass("repo rep " + (repo.language || '').toLowerCase());
        var $link = $("<a>").attr("href", repoUrl(repo)).appendTo($item);
        $link.append($("<h2>").text(repo.name));
        // $link.append($("<h3>").text(repo.watchers + " watchers" + " / " + repo.open_issues + " open issues"));
        $link.append($("<p style='line-height:1em;'>").text(repoDescription(repo)));
        //$link.append($("<p style='line-height:1em;'>").text("Updated " +
        //  strftime("%h %e, %Y", repo.pushed_at)));
        $link.append($("<h3 style='top:23px; right:1px;'>").addClass("language").text(repo.language));

        $item.appendTo("#repos");
      }
      //var tokenkey='9594d317ed5';
      var promises=[]; //to store the array of returned promises of each query.
      var temprepos=[];
      // This is to return the promises of every query on different urls.
      function queryorgrepo(requrl){
      return $.ajax({
      //$.ajax({
         url: requrl,
         //async: false,
         dataType: 'json',
         //headers: 'Authorization: token '+tokenkey,
         success: function () {
         //We only need results.data. Is this blank function correct?
         // return result.data;
         }
      });
      //return repos;
      //console.log(promises);
      };
      
      var orgnames = ['CQuIC', 
                      'JuliaCN', 
                      'JuliaQuantum', 
                      'ICIQ'];
      //Define url list as a combination of user's url and the orgs' urls.
      var orgurls = ['https://api.github.com/users/i2000s/repos?per_page=100&callback=?'];
      for (var indx = 0; indx < orgnames.length; indx++){
        orgurls[indx + 1] = "https://api.github.com/orgs/"+orgnames[indx]+"/repos?per_page=100&callback=?";
      };
      //alert(orgurls);
      for (var indx = 0; indx < orgurls.length; indx++){
        //repos=$.merge(repos,queryorgrepo(orgurls[indx]));
        promises.push(queryorgrepo(orgurls[indx]));
        //temprepos.push(queryorgrepo(orgurls[indx]));
        //results.push(queryorgrepo(orgurls[indx]));
        //console.log(promises);
       }
      //alert(promises);
      //alert(repos);
      // invoke each function stored in the result array and proceed when they are all done
      $.when.apply(this, promises).done(function () {
      // fetch the result from each arg
      var tempdata = [];
      // each arg contains the result of one succes ajax function.
      // in this case, three arguments exist, one for each ajax call.
        for (var i = 0; i < arguments.length; i++) {
        // retrieve the entries from the argument parameter
          values = arguments[i][0].data;
          console.log(values);

         // push the retrieved value to a global function variable, which we can.
         // this function is processed synchronously, when all ajax calls have been completed
         tempdata.push(values);
        };

      // merge the arrays to get the collected repos.
      for (var i = 0; i < tempdata.length; i++) {
        $.merge(repos, tempdata[i]);
      };
      
      //  console.log(repos);
      // sort the repos and define html elememts.
      $(function () {
          $("#num-repos").text(repos.length);

          // Convert pushed_at to Date.
          $.each(repos, function (i, repo) {
            repo.pushed_at = new Date(repo.pushed_at);

            var weekHalfLife  = 1.146 * Math.pow(10, -9);

            var pushDelta    = (new Date) - Date.parse(repo.pushed_at);
            var createdDelta = (new Date) - Date.parse(repo.created_at);

            var weightForPush = 1;
            var weightForWatchers = 1.314 * Math.pow(10, 7);

            repo.hotness = weightForPush * Math.pow(Math.E, -1 * weekHalfLife * pushDelta);
            repo.hotness += weightForWatchers * repo.watchers / createdDelta;
          });

          // Sort by highest # of watchers.
          repos.sort(function (a, b) {
            if (a.hotness < b.hotness) return 1;
            if (b.hotness < a.hotness) return -1;
            return 0;
          });
          // Only first 12 hotest repos are shown.
          $.each(repos.slice(0,12), function (i, repo) {
            addRepo(repo);
          });

          // Sort by most-recently pushed to.
          repos.sort(function (a, b) {
            if (a.pushed_at < b.pushed_at) return 1;
            if (b.pushed_at < a.pushed_at) return -1;
            return 0;
          });

          $.each(repos.slice(0, 3), function (i, repo) {
            addRecentlyUpdatedRepo(repo);
          });
        });//function
        //alert(repos);
      }); //when.apply.done
    })(jQuery);

可以在 http://i2000s.github.io/community/ 找到使用此代码的实时网页。您也可以修改代码以查询其他网址。