如何利用AngularJS服务接入外部API

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了如何利用AngularJS服务接入外部API相关的知识,希望对你有一定的参考价值。

如何利用AngularJS服务接入外部API

除了对HTML进行扩展的能力之外,AngularJS还提供一套简便途径、帮助我们与外部API实现交互。利用其服务与GitHub的API相对接,进而创建一套简单的库浏览器。

现在用这套基础HTML模板为起点

一、准备工作

现在将AngularJS脚本添加到该文档的<head>当中:

在此之后,可以在将这套CCS样式添加到行内或者独立的文件当中:

其中不存在任何多余的内容、只保留最基础的布局方案——将搜索栏置于右侧、库信息位于中央、用户库同样置于右侧。还需要将对应代码行打包至<pre>标签当中,此后还要利用它显示README文件内容——因为这些内容通常来自GitHub Flavored Markdown、而且其中一部分代码行与用户库列表存在重叠。

可以向其中添加更多样式以提升成果的视觉效果——但以上截图都采取最基本的外观设计。

在未来需要编写的JavaScript代码置于本文档的<head>当中或者为其建立独立文件,但独立文件仍然需要处于AngularJS脚本之下

二、模块

现在可以为自己的应用程序创建一个模块:

接下来利用ngApp指令将其添加到<body>标签当中:

三、控制器

需要为自己的应用程序准备一套控制器。为了简化创建流程,将只为应用准备一套控制器,这样就不必考虑如何在不同控制器之间进行信息传递了

四、基础服务

需要对自己的GitHub服务进行定义:

将使用app.factory()方法,这样就能保证返回对象附带几个以后将会用到的方法。将使用$http服务从GitHub的API中获取数据。

五、搜索库

服务中的第一项方法负责利用GitHub API对库进行搜索。使用服务非常简单(这项函数能够进入由制造函数返回的对象):

$http.get()方法是执行GET请求的一种捷径。第一条参数是希望访问的URL。第二条参数则代表一个具备选项的对象。这里只需要params对象——它是一个查询参数散列,将被添加到该请求当中(其中q参数属于搜索字符串)。

$http.get()会返回一项承诺。可以将监听器附加在success()与error()上,并且据此调用回调函数。

六、搜索栏

为了使用之前几步中定义完成的函数,需要在自己的HTML当中添加搜索栏。相关代码非常简单,如下所示:

使用ngModel指令将该输入栏中的值指向至Scope query变量,并在用户按下回车键后利用ngKeyup调用executeSearch()函数(这样$event.keyCode == 13就会进行比较)。无法在AngularJS表达式中使用条件语句,但一条简单的逻辑运算符(AND)足以很好地完成这项任务。

在输入域下面,使用ngRepeat来显示搜索结果。将显示该库的完整名称与描述(如果需要显示其它不同内容,可以点击此处查看GitHub API说明文档中的可用域)。

还使用ngClick通过该库的完整名称来调用openRepo()函数,这样就能显示与之相关的信息,稍后再对该函数进行定义。

七、使用搜索功能

现在可以使用自己创建完成的服务了。首先,将GitHub参数添加至控制器函数(这样该服务就能被注入到AngularJS当中):

现在定义executeSearch()函数:

利用来自$scope.query的搜索字符串从当中调用GitHub.searchRepos(),而后在回调中将搜索结果(来自data.items)加入$scope.repos变量。

只要执行以上步骤,就能顺利显示出搜索结果。在浏览器中打开HTML文件并尝试进行搜索:

八、获取库中的数据

被传递至此函数的名称必须为完整名称(结构为:作者名称、斜杠、库名称——例如angular/angular.js),这是因为需要将其传递至GitHub API。

九、获取库中的README文件

README文件中的内容并未被包含在我利用以上函数获取到的数据当中。相反,需要利用另一个API进行调用及获取,因此需要创建以下函数:

这条函数与之前我们创建完毕的两条基本相同,只不过对URL进行了变更。还要利用atob()函数解码README文件的内容,因为它采用base64编码机制。可以点击此处查看GitHub API说明文档中与获取README文件内容相关的信息。

之所以没有将这两条请求塞进同一个函数当中,是因为某些库根本不具备 README文件。如果将二者强行结合,应用程序可能因此发生故障。

十、显示库信息

将在另一个元素<div>当中显示库的完整名称、查看过该库的人数以及README文件:

将把该信息保存在控制器Scope内的activeRepo变量当中。只要存在可以显示的数据,ngShow就会将该元素显示出来(如果不存在可以显示的数据,将只能看到‘Watched by people’文本,而且没有任何库被选中)。

十一、更新控制器

还需要对控制器进行更新,从而保证其切实获取到库数据并将其纳入Scope当中。下面创建之前附加至ngClick指令的openRepo()函数:

在这里,首先使用GitHub.getRepo()方法、检查错误而后将该数据引入activeRepo变量。接下来,获取README文件——如果该文件不存在,需要向用户提示该情况。

现在可以再次运行自己的应用程序并查看其实际效果:

十二、获取用户的库

为了将更多功能引入到应用程序当中,将为屏幕右方已被选定库的持有者显示其所有可用库。这要求向服务中引入另一个方法:

十三、显示用户的库

这基本上相当于重现HTML中的搜索栏机制,不过实际需要显示的是用户名称与user对象中的库,而非输入域或者Scope本身:

到了这一步,应该已经拥有了一套能够切实运作的AngularJS应用程序——它可以根据搜索字符串获取GitHub库。

参考技术A 第一步:准备工作
 将AngularJS脚本添加到该文档的当中:  
  在此之后,可以在将这套CCS样式添加到行内或者独立的文件当中:
  *
  -webkit-box-sizing:border-box;
  -moz-box-sizing:border-box;
  box-sizing:border-box;
  font-family:sans-serif;
  
  body,htmlmargin:0;
  pmargin:0;
  inputwidth:100%;
  pre
  white-space:pre-wrap;
  white-space:-moz-pre-wrap;
  white-space:-pre-wrap;
  white-space:-o-pre-wrap;
  word-wrap:break-word;
  
  div.repo
  border-bottom:1pxsolid;
  cursor:pointer;
  
  #search,#repo,#userfloat:left;
  #searchwidth:20%;
  #repowidth:60%;
  #userwidth:20%;
  如大家所见,其中不存在任何多余的内容、只保留最基础的布局方案——将搜索栏置于右侧、库信息位于中央、用户库同样置于右侧。我们还需要将对应代码行打包至标签当中,此后我们还要利用它显示README文件内容——因为这些内容通常来自GitHub Flavored Markdown、而且其中一部分代码行与用户库列表存在重叠。
  当然,大家可以向其中添加更多样式以提升成果的视觉效果——但请注意,本教程中的截图都采取最基本的外观设计。
  大家可以未来需要编写的JavaScript代码置于本文档的当中或者为其建立独立文件,但独立文件仍然需要处于AngularJS脚本之下。
  第二步:模块
  现在我们可以为自己的应用程序创建一个模块:
  varapp=angular.module('githubsearch',[]);
  接下来利用ngApp指令将其添加到标签当中:  
  第三步:控制器
  我们还需要为自己的应用程序准备一套控制器。为了简化创建流程,我们将只为应用准备一套控制器,这样我们就不必考虑如何在不同控制器之间进行信息传递了:
  app.controller('SearchController',functionSearchController($scope)
  );
  第四步:基础服务
  我们需要对自己的GitHub服务进行定义:
  app.factory('GitHub',functionGitHub($http)
  return
  ;
  );
  我们将使用app.factory()方法,这样就能保证返回对象附带几个以后将会用到的方法。我们将使用$http服务从GitHub的API中获取数据。
参考技术B   如何利用AngularJS服务接入外部API
  除了轻松对HTML进行扩展的能力之外,AngularJS还提供一套简便途径、帮助我们与外部API实现交互。在今天的教程中,我们将共同探讨如何利用其服务与GitHub的API相对接,进而创建一套简单的库浏览器。
  第一步:准备工作
  我们就以下面这套基础HTML模板为起点:
  <!DOCTYPE html> <html> <head> <title>GitHub Search</title> </head> <body> </body> </html>

  现在将AngularJS脚本添加到该文档的<head>当中:
  <script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.16/angular.min.js"></script>

  在此之后,我们可以在将这套CCS样式添加到行内或者独立的文件当中:

  * -webkit-box-sizing: border-box; -moz-box-sizing: border-box; box-sizing: border-box; font-family: sans-serif; body, html margin: 0; p margin: 0; input width: 100%; pre white-space: pre-wrap; white-space: -moz-pre-wrap; white-space: -pre-wrap; white-space: -o-pre-wrap; word-wrap: break-word; div.repo border-bottom: 1px solid; cursor: pointer; #search, #repo, #user float: left; #search width: 20%; #repo width: 60%; #user width: 20%;

  如大家所见,其中不存在任何多余的内容、只保留最基础的布局方案——将搜索栏置于右侧、库信息位于中央、用户库同样置于右侧。我们还需要将对应代码行打包至<pre>标签当中,此后我们还要利用它显示README文件内容——因为这些内容通常来自GitHub Flavored Markdown、而且其中一部分代码行与用户库列表存在重叠。
  当然,大家可以向其中添加更多样式以提升成果的视觉效果——但请注意,本教程中的截图都采取最基本的外观设计。
  大家可以未来需要编写的JavaScript代码置于本文档的<head>当中或者为其建立独立文件,但独立文件仍然需要处于AngularJS脚本之下。
  第二步:模块
  现在我们可以为自己的应用程序创建一个模块:
  var app = angular.module('githubsearch', []);

  接下来利用ngApp指令将其添加到<body>标签当中:
  <body ng-app="githubsearch">

  第三步:控制器
  我们还需要为自己的应用程序准备一套控制器。为了简化创建流程,我们将只为应用准备一套控制器,这样我们就不必考虑如何在不同控制器之间进行信息传递了:

  app.controller('SearchController', function SearchController($scope) );

  第四步:基础服务
  我们需要对自己的GitHub服务进行定义:

  app.factory('GitHub', function GitHub($http) return ; );

  我们将使用app.factory()方法,这样就能保证返回对象附带几个以后将会用到的方法。我们将使用$http服务从GitHub的API中获取数据。
  第五步:搜索库
  我们服务中的第一项方法负责利用GitHub API对库进行搜索。使用服务非常简单(这项函数能够进入由制造函数返回的对象):

  searchRepos: function searchRepos(query, callback) $http.get('https://api.github.com/search/repositories', params: q: query ) .success(function (data) callback(null, data); ) .error(function (e) callback(e); );

  $http.get()方法是执行GET请求的一种捷径。第一条参数是我们希望访问的URL。第二条参数则代表一个具备选项的对象。这里我们只需要params对象——它是一个查询参数散列,将被添加到该请求当中(其中q参数属于搜索字符串,大家可以点击此处了解更多相关信息)。
  $http.get()会返回一项承诺。我们可以将监听器附加在success()与error()上,并且据此调用回调函数。
  第六步:搜索栏
  为了使用我们在之前几步中定义完成的函数,我们需要在自己的HTML当中添加搜索栏。相关代码非常简单,如下所示:

  <div id="search"> <input ng-model="query" placeholder="search" ng-keyup="$event.keyCode == 13 && executeSearch()"> <div class="repo" ng-repeat="repo in repos" ng-click="openRepo(repo.full_name)"> <strong> repo.full_name </strong> <p> repo.description </p> </div> </div>

  我们使用ngModel指令将该输入栏中的值指向至Scope query变量,并在用户按下回车键后利用ngKeyup调用executeSearch()函数(这样$event.keyCode == 13就会进行比较)。我们无法在AngularJS表达式中使用条件语句,但一条简单的逻辑运算符(AND)足以很好地完成这项任务。
  在输入域下面,我们使用ngRepeat来显示搜索结果。我们将显示该库的完整名称与描述(如果需要显示其它不同内容,大家可以点击此处查看GitHub API说明文档中的可用域)。
  我们还使用ngClick通过该库的完整名称来调用openRepo()函数,这样我们就能显示与之相关的信息。我们稍后再对该函数进行定义。
  第七步:使用搜索功能

  现在我们终于可以使用自己创建完成的服务了。首先,将GitHub参数添加至控制器函数(这样该服务就能被注入到AngularJS当中):
  app.controller('SearchController', function SearchController($scope)

  现在定义executeSearch()函数:

  $scope.executeSearch = function executeSearch() GitHub.searchRepos($scope.query, function (error, data) if (!error) $scope.repos = data.items; );

  如大家所见,我们利用来自$scope.query的搜索字符串从当中调用GitHub.searchRepos(),而后在回调中将搜索结果(来自data.items)加入$scope.repos变量。

  只要执行以上步骤,我们就能顺利显示出搜索结果。在浏览器中打开我们的HTML文件并尝试进行搜索:

  第八步:获取库中的数据

  现在我们已经获得了搜索功能,可以显示出库中用户所选定的信息内容。下面我们再创建一条函数,旨在通过自己的服务获取来自库的数据:

  getRepo: function getRepo(name, callback) $http.get('https://api.github.com/repos/'+ name) .success(function (data) callback(null, data); ) .error(function (e) callback(e); );

  被传递至此函数的名称必须为完整名称(结构为:作者名称、斜杠、库名称——例如angular/angular.js),这是因为我们需要将其传递至GitHub
API(点击此处查看更多说明)。

  第九步:获取库中的README文件

  README文件中的内容并未被包含在我们利用以上函数获取到的数据当中。相反,大家需要利用另一个API进行调用及获取,因此我们需要创建以下函数:
  getReadme: function getReadme(name, callback) $http.get('https://api.github.com/repos/'+ name +'/readme') .success(function (data) callback(null, atob(data.content)); ) .error(function (e) callback(e); );

  这条函数与之前我们创建完毕的两条基本相同,只不过对URL进行了变更。我们还要利用atob()函数解码README文件的内容,因为它采用base64编码机制。大家可以点击此处查看GitHub
API说明文档中与获取README文件内容相关的信息。

  我们之所以没有将这两条请求塞进同一个函数当中,是因为某些库根本不具备 README文件。如果我们将二者强行结合,应用程序可能因此发生故障。

  第十步:显示库信息

  我们将在另一个元素<div>当中显示库的完整名称、查看过该库的人数以及README文件:

  <div id="repo" ng-show="activeRepo"> <strong> activeRepo.full_name </strong> <em>Watched by activeRepo.watchers_count people.</em> <pre> activeRepo.readme </pre> </div>

  我们将把该信息保存在控制器Scope内的activeRepo变量当中。只要存在可以显示的数据,ngShow就会将该元素显示出来(如果不存在可以显示的数据,我们将只能看到‘Watched
by people’文本,而且没有任何库被选中)。

  第十一步:更新控制器

  我们还需要对控制器进行更新,从而保证其切实获取到库数据并将其纳入Scope当中。下面创建我们之前附加至ngClick指令的openRepo()函数:

  $scope.openRepo = function openRepo(name) GitHub.getRepo(name, function (error, data) if (!error) $scope.activeRepo = data; GitHub.getReadme(name, function (error, data) if (!error) $scope.activeRepo.readme = data; else $scope.activeRepo.readme = 'No README found!'; ); );

  如大家所见,我们首先使用GitHub.getRepo()方法、检查错误而后将该数据引入activeRepo变量。接下来,我们获取README文件——如果该文件不存在,我们需要向用户提示该情况。

  现在大家可以再次运行自己的应用程序并查看其实际效果:

  第十二步:获取用户的库

  为了将更多功能引入到我们的应用程序当中,我们将为屏幕右方已被选定库的持有者显示其所有可用库。这要求我们向服务中引入另一个方法:

  getUserRepos: function getUser(name, callback) $http.get('https://api.github.com/users/'+ name +'/repos') .success(function (data) callback(null, data); ) .error(function (e) callback(e); );

  其内容与此前的几条几乎无甚差别(大家可以点击此处查看更多与此API请求相关的信息)。

  第十三步:显示用户的库

  这基本上相当于重现HTML中的搜索栏机制,不过我们实际需要显示的是用户名称与user对象中的库,而非输入域或者Scope本身:

  <div id="user"> <strong> user.login </strong> <div class="repo" ng-repeat="repo in user.repos" ng-click="openRepo(repo.full_name)"> <strong> repo.name </strong> <p> repo.description </p> </div> </div>

  到了这一步,大家应该已经拥有了一套能够切实运作的AngularJS应用程序——它可以根据搜索字符串获取GitHub库。大家可以进一步对其进行迭代,例如向其中添加更多功能或者为其设计完全不同的外观样式。
转载,仅供参考,祝你愉快,满意请采纳。  本回答被提问者和网友采纳
参考技术C 第一步:准备工作
 将AngularJS脚本添加到该文档的当中:  
  在此之后,可以在将这套CCS样式添加到行内或者独立的文件当中:
  *
  -webkit-box-sizing:border-box;
  -moz-box-sizing:border-box;
  box-sizing:border-box;
  font-family:sans-serif;
  
  body,htmlmargin:0;
  pmargin:0;
  inputwidth:100%;
  pre
  white-space:pre-wrap;
  white-space:-moz-pre-wrap;
  white-space:-pre-wrap;
  white-space:-o-pre-wrap;
  word-wrap:break-word;
  
  div.repo
  border-bottom:1pxsolid;
  cursor:pointer;
  
  #search,#repo,#userfloat:left;
  #searchwidth:20%;
  #repowidth:60%;
  #userwidth:20%;
  如大家所见,其中不存在任何多余的内容、只保留最基础的布局方案——将搜索栏置于右侧、库信息位于中央、用户库同样置于右侧。我们还需要将对应代码行打包至标签当中,此后我们还要利用它显示README文件内容——因为这些内容通常来自GitHub Flavored Markdown、而且其中一部分代码行与用户库列表存在重叠。
  当然,大家可以向其中添加更多样式以提升成果的视觉效果——但请注意,本教程中的截图都采取最基本的外观设计。
  大家可以未来需要编写的JavaScript代码置于本文档的当中或者为其建立独立文件,但独立文件仍然需要处于AngularJS脚本之下。
  第二步:模块
  现在我们可以为自己的应用程序创建一个模块:
  varapp=angular.module('githubsearch',[]);
  接下来利用ngApp指令将其添加到标签当中:  
  第三步:控制器
  我们还需要为自己的应用程序准备一套控制器。为了简化创建流程,我们将只为应用准备一套控制器,这样我们就不必考虑如何在不同控制器之间进行信息传递了:
  app.controller('SearchController',functionSearchController($scope)
  );
  第四步:基础服务
  我们需要对自己的GitHub服务进行定义:
  app.factory('GitHub',functionGitHub($http)
  return
  ;
  );
  我们将使用app.factory()方法,这样就能保证返回对象附带几个以后将会用到的方法。我们将使用$http服务从GitHub的API中获取数据。
  第五步:搜索库
  我们服务中的第一项方法负责利用GitHub API对库进行搜索。使用服务非常简单(这项函数能够进入由制造函数返回的对象):
  searchRepos:functionsearchRepos(query,callback)
  $http.get('https://api.github.com/search/repositories',params:q:query)
  .success(function(data)
  callback(null,data);
  )
  .error(function(e)
  callback(e);
  );
  
  $http.get()方法是执行GET请求的一种捷径。第一条参数是我们希望访问的URL。第二条参数则代表一个具备选项的对象。这里我们只需要params对象——它是一个查询参数散列,将被添加到该请求当中(其中q参数属于搜索字符串,大家可以点击此处了解更多相关信息)。
  $http.get()会返回一项承诺。我们可以将监听器附加在success()与error()上,并且据此调用回调函数。
  第六步:搜索栏
  为了使用我们在之前几步中定义完成的函数,我们需要在自己的HTML当中添加搜索栏。

如何在 AngularJS 中正确使用 HTTP.GET?具体来说,对于外部 API 调用?

【中文标题】如何在 AngularJS 中正确使用 HTTP.GET?具体来说,对于外部 API 调用?【英文标题】:How to use HTTP.GET in AngularJS correctly? In specific, for an external API call? 【发布时间】:2013-12-20 14:03:51 【问题描述】:

我在controller.js中有如下代码,

var myApp = angular.module('myApp',[]);

myApp.service('dataService', function($http) 
delete $http.defaults.headers.common['X-Requested-With'];
this.getData = function() 
    $http(
        method: 'GET',
        url: 'https://www.example.com/api/v1/page',
        params: 'limit=10, sort_by=created:desc',
        headers: 'Authorization': 'Token token=xxxxYYYYZzzz'
     ).success(function(data)
         return data
    ).error(function()
        alert("error");
    );
 
);

myApp.controller('AngularJSCtrl', function($scope, dataService) 
  $scope.data = dataService.getData();
);

但是,我想我可能在 CORS 相关问题上犯了一个错误。你能指点我打这个电话的正确方法吗?非常感谢!

【问题讨论】:

这是一个超级常见的问题:) 【参考方案1】:

以 Google 财经为例,检索代码的最后收盘价和更新的日期和时间。您可以访问 YouTiming.com 进行运行时执行。

服务:

MyApp.service('getData', 
  [
    '$http',
    function($http) 

      this.getQuote = function(ticker) 
        var _url = 'https://www.google.com/finance/info?q=' + ticker;
        return $http.get(_url); //Simply return the promise to the caller
      ;
    
  ]
);

控制器:

MyApp.controller('StockREST', 
  [
    '$scope',
    'getData', //<-- the service above
    function($scope, getData) 
      var getQuote = function(symbol) 
        getData.getQuote(symbol)
        .success(function(response, status, headers, config) 
          var _data = response.substring(4, response.length);
          var _json = JSON.parse(_data);
          $scope.stockQuoteData = _json[0];
          // ticker: $scope.stockQuoteData.t
          // last price: $scope.stockQuoteData.l
          // last updated time: $scope.stockQuoteData.ltt, such as "7:59PM EDT"
          // last updated date & time: $scope.stockQuoteData.lt, such as "Sep 29, 7:59PM EDT"
        )
        .error(function(response, status, headers, config) 
          console.log('@@@ Error: in retrieving Google Finance stock quote, ticker = ' + symbol);
        );
      ;

      getQuote($scope.ticker.tick.name); //Initialize
      $scope.getQuote = getQuote; //as defined above
    
  ]
);

HTML:

<span>stockQuoteData.l, stockQuoteData.lt</span>

在 YouTiming.com 主页的顶部,我放置了关于如何在 Chrome 和 Safari 上禁用 CORS 策略的注释。

【讨论】:

【参考方案2】:

首先,您的success() 处理程序只返回数据,但不会返回给getData() 的调用者,因为它已经在回调中。 $http 是一个异步调用,它返回一个$promise,所以你必须注册一个回调来等待数据可用。

我建议在 AngularJS 中查找 Promises 和 $q library,因为它们是在服务之间传递异步调用的最佳方式。

为简单起见,以下是使用调用控制器提供的函数回调重写的相同代码:

var myApp = angular.module('myApp',[]);

myApp.service('dataService', function($http) 
    delete $http.defaults.headers.common['X-Requested-With'];
    this.getData = function(callbackFunc) 
        $http(
            method: 'GET',
            url: 'https://www.example.com/api/v1/page',
            params: 'limit=10, sort_by=created:desc',
            headers: 'Authorization': 'Token token=xxxxYYYYZzzz'
        ).success(function(data)
            // With the data succesfully returned, call our callback
            callbackFunc(data);
        ).error(function()
            alert("error");
        );
     
);

myApp.controller('AngularJSCtrl', function($scope, dataService) 
    $scope.data = null;
    dataService.getData(function(dataResponse) 
        $scope.data = dataResponse;
    );
);

现在,$http 实际上已经返回了一个 $promise,所以可以重写:

var myApp = angular.module('myApp',[]);

myApp.service('dataService', function($http) 
    delete $http.defaults.headers.common['X-Requested-With'];
    this.getData = function() 
        // $http() returns a $promise that we can add handlers with .then()
        return $http(
            method: 'GET',
            url: 'https://www.example.com/api/v1/page',
            params: 'limit=10, sort_by=created:desc',
            headers: 'Authorization': 'Token token=xxxxYYYYZzzz'
         );
     
);

myApp.controller('AngularJSCtrl', function($scope, dataService) 
    $scope.data = null;
    dataService.getData().then(function(dataResponse) 
        $scope.data = dataResponse;
    );
);

最后,有更好的方法来配置$http 服务来为您处理标头,使用config() 来设置$httpProvider。查看$http documentation 获取示例。

【讨论】:

@Kevin:我是 ANG 新手,我不清楚,为什么不在你重新编写的代码中的服务中使用 .success 和 .error 方法?我们需要在控制器中使用它吗?如何 ?任何示例来显示成功/错误和数据、配置参数? 我使用.then(),它是promise 接口,它与.success() 基本相同,但可以链接。 .success/.error 基本上已被承诺弃用【参考方案3】:

调用服务或工厂中定义的承诺时,请确保使用服务,因为我无法从工厂中定义的承诺中获得响应。这就是我如何称呼服务中定义的承诺。

myApp.service('serverOperations', function($http) 
        this.get_data = function(user) 
          return $http.post('http://localhost/serverOperations.php?action=get_data', user);
        ;
)


myApp.controller('loginCtrl', function($http, $q, serverOperations, user)         
    serverOperations.get_data(user)
        .then( function(response) 
            console.log(response.data);
            
        );
)

【讨论】:

【参考方案4】:

不需要用 $http 承诺,我只用它有两个回报:

 myApp.service('dataService', function($http) 
   this.getData = function() 
      return $http(
          method: 'GET',
          url: 'https://www.example.com/api/v1/page',
          params: 'limit=10, sort_by=created:desc',
          headers: 'Authorization': 'Token token=xxxxYYYYZzzz'
      ).success(function(data)
        return data;
      ).error(function()
         alert("error");
         return null ;
      );
   
 );

在控制器中

 myApp.controller('AngularJSCtrl', function($scope, dataService) 
     $scope.data = null;
     dataService.getData().then(function(response) 
         $scope.data = response;
     );
 ); 

【讨论】:

【参考方案5】:

所以你需要使用我们所说的promise。在此处阅读 Angular 如何处理它,https://docs.angularjs.org/api/ng/service/$q。将我们的 $http 支持承诺变成固有的,所以在你的情况下,我们会做这样的事情,

(function() 
  "use strict";
  var serviceCallJson = function($http) 

      this.getCustomers = function() 
        // http method anyways returns promise so you can catch it in calling function
        return $http(
            method : 'get',
            url : '../viewersData/userPwdPair.json'
          );
      

  

  var validateIn = function (serviceCallJson, $q) 

      this.called = function(username, password) 
          var deferred = $q.defer(); 
          serviceCallJson.getCustomers().then( 
            function( returnedData ) 
              console.log(returnedData); // you should get output here this is a success handler
              var i = 0;
              angular.forEach(returnedData, function(value, key)
                while (i < 10) 
                  if(value[i].username == username) 
                    if(value[i].password == password) 
                     alert("Logged In");
                    
                  
                  i = i + 1;
                
              );
            , 
            function() 

              // this is error handler
             
          );
          return deferred.promise;  
      

  

  angular.module('assignment1App')
    .service ('serviceCallJson', serviceCallJson)

  angular.module('assignment1App')
  .service ('validateIn', ['serviceCallJson', validateIn])

())

【讨论】:

【参考方案6】:

试试这个

myApp.config(['$httpProvider', function($httpProvider) 
        $httpProvider.defaults.useXDomain = true;
        delete $httpProvider.defaults.headers.common['X-Requested-With'];
    
]);

仅设置 useXDomain = true 是不够的。 AJAX 请求也与 X-Requested-With 标头一起发送,这表明它们是 AJAX。删除标头是必要的,因此服务器不会拒绝传入的请求。

【讨论】:

【参考方案7】:

我建议你使用 Promise

myApp.service('dataService', function($http,$q) 

  delete $http.defaults.headers.common['X-Requested-With'];
  this.getData = function() 
     deferred = $q.defer();
     $http(
         method: 'GET',
         url: 'https://www.example.com/api/v1/page',
         params: 'limit=10, sort_by=created:desc',
         headers: 'Authorization': 'Token token=xxxxYYYYZzzz'
     ).success(function(data)
         // With the data succesfully returned, we can resolve promise and we can access it in controller
         deferred.resolve();
     ).error(function()
          alert("error");
          //let the function caller know the error
          deferred.reject(error);
     );
     return deferred.promise;
  
);

所以在你的控制器中你可以使用该方法

myApp.controller('AngularJSCtrl', function($scope, dataService) 
    $scope.data = null;
    dataService.getData().then(function(response) 
        $scope.data = response;
    );
);

promises 是 angularjs 的强大功能,如果你想避免嵌套回调,它特别方便。

【讨论】:

$http 已经返回了一个承诺。将 $http 包装在另一个 Promise 中是多余的。 在 $http 承诺上使用 .then 不会像 .success 那样直接返回数据 我完全按照上面的方法进行操作,但在控制器中出现错误“无法读取未定义的属性 'then'”。修复:完全删除 deferred/promise 并简单地 return $http(); 如第一条评论中所述

以上是关于如何利用AngularJS服务接入外部API的主要内容,如果未能解决你的问题,请参考以下文章

如何利用AngularJs快速搭建前端基本框架

如何利用AngularJS打造一款简单Web应用

使用 AngularJS 和外部 NodeJS 服务器启用 html5 模式

架构设计|异步请求如何同步处理?

如何利用AngularJs快速搭建前端基本框架

如何将实时数据从 nodejs 服务器推送到 AngularJS?