如何在Angular中发出$ http请求后才能运行javascript函数?

时间:2015-11-27 09:29:11

标签: javascript angularjs http

我正在使用一个Angular.js应用程序来调用GitHub API。首先,调用以检索用户的所有存储库。然后,对于每个repo,进行调用以检索README。我有一个javascript函数,我希望只有在所有README API调用完成后才能运行。

这是我的控制器:

readmeSearch.controller('ReadMeSearchController', ['RepoSearch', 'ReadMeSearch', function(RepoSearch, ReadMeSearch) {

  var self = this;
  self.gitRepoNames = [];
  self.readMes = [];
  self.noReadMes = [];

  self.doSearch = function() {
    RepoSearch.query(self.username)
      .then(function(repoResponse) {
        addRepoNames(repoResponse);
        for(var i = 0; i< self.gitRepoNames.length; i++) {
          (function(i) {
            ReadMeSearch.query(self.username, self.gitRepoNames[i])
              .then(function(readMeResponse) {
                addToReposWithReadMes(readMeResponse, i);
              }).catch(function(e){
                addToReposWithoutReadMes(repoResponse, i);
              });
          })(i);
        };
      });
  };

  addRepoNames = function(response) {
    self.searchResult = response.data;
    for(var i = 0; i < self.searchResult.length; i++) {
      var name = self.searchResult[i]['name']
      self.gitRepoNames.push(name);
    };
  };

  addToReposWithReadMes = function(response, i) {
    self.readMes.push(
      {
        name: self.gitRepoNames[i],
        size: parseInt(response.data["size"]),
        url: response.data["html_url"]
      }
    );
  };

  addToReposWithoutReadMes = function(response, i) {
    self.noReadMes.push(
      {
        name: self.gitRepoNames[i]
      }
    );
  };

  percentageOfReposWithReadMes = function() {
    var percentage;
    percentage = (self.noReadMes.length / self.gitRepoNames.length) * 100
    self.readMePercentage = percentage.toFixed(1);
  };

}]);

使用ReadMeSearch工厂的README API调用填充两个数组,一个用于带有README的repos,另一个用于没有README的repos。我想在percentageOfReposWithReadMes完成ReadMeSearch.query中的所有回购后,才能运行self.gitRepoNames函数。

我已尝试在.then之后使用RepoSearch.query,但这似乎不起作用。我认为我对Angular承诺和.then函数的理解有点混乱。任何帮助将不胜感激。

3 个答案:

答案 0 :(得分:0)

您可以尝试使用$q.all,这将重新获得一系列承诺,.then完成所有这些后,您将运行您的功能。

我自己尝试这个问题,如果你有一个笨蛋或其他东西会更容易。

我确实找到了解释这个问题的this帖子,也许你可以在那里找到答案。

答案 1 :(得分:0)

我认为你必须创建两个延迟并在循环结束时解决。使用$ q.all,您可以等待两个引用完成并调用<?php $dates = ""; foreach ($check_ins as $check_in): $dates .= '<option value= "' . $check_in['check_in'] . '">' . $check_in['check_in'] . '</option>'; endforeach; $nights = $check_ins[0]['nights']; if (!empty($_POST['newDate'])){ $nights = 0; foreach ($check_ins as $check_in): if ($check_in['check_in'] === $_POST['newDate']){ $nights += $check_in['nights']; } endforeach; } ?> <html> <head> <title>Bookings stats</title> <script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script> <script> /*function dynamicDates() { var d = $("#dates").val(); $.post("metrily.php", { newDate: d }); }*/ function dynamicDates(newDate){ if (newDate == ""){ document.getElementById("stats").innerHTML = ""; return; } else { xmlhttp = new XMLHttpRequest(); xmlhttp.onreadystatechange = function() { if (xmlhttp.readyState == 4 && xmlhttp.status == 200){ document.getElementById("stats").innerHTML = xmlhttp.responseTest; } }; xmlhttp.open("POST", "hotel.php", true); xmlhttp.send("newDate=" + newDate); } } </script> </head> <body> <b>Check-in: </b> <select id="dates" name="check_in" onchange="dynamicDates(this.value)"><?php echo $dates; ?></select> <br></br> <div id="stats"> <b>Nights: </b><?php echo $nights; ?> </div> </body> </html> 函数。

percentageOfReposWithReadMes

答案 2 :(得分:0)

从这些承诺中退回您的承诺和

 self.doSearch = function() {
    var namesPromise = 
        RepoSearch.query(self.username)
            .then(function(repoResponse) {
                 addRepoNames(repoResponse);
                 //return promises for chaining
                 return lookupNamesPromises(repoResponse);
            }) .catch (function (error) {
                 //log error
            });
    //chain from promise
    namesPromise.then (function(promises) {
        $q.all(promises).finally( function() {
            percentageOfReposWithReadMes();
        })
    });
    //return promise for chaining elsewhere
    return namesPromise;
  };

Lookup函数返回一个promise数组。

  self.lookupNamesPromises = function (repoResponse) {
    var namesPromises = [];
    for(var i = 0; i< self.gitRepoNames.length; i++) {
          //begin IIFE closure
          (function(i) {
              var p = (ReadMeSearch.query(self.username, self.gitRepoNames[i])
                       .then(function(readMeResponse) {
                           addToReposWithReadMes(readMeResponse, i);
                           return readMeResponse;
                       }).catch(function(e){
                           addToReposWithoutReadMes(e, i);
                           return e;
                       })
              );
              namesPromises.push(p);
          })(i);
          //end IIFE closure
    }
           //return promises for chaining
    return namesPromises;
  };

通过链接您的承诺,后续功能将等待以前的功能完成。函数式编程的经验法则总是返回