99re热这里只有精品视频,7777色鬼xxxx欧美色妇,国产成人精品一区二三区在线观看,内射爽无广熟女亚洲,精品人妻av一区二区三区

AngularJS REST和自定義服務(wù)

2022-04-15 14:37 更新

REST和自定義服務(wù)

在這一步中,你將改變我們獲取數(shù)據(jù)的方法。

  • 我們定義了一個(gè)自定義服務(wù),它代表了一個(gè)RESTful客戶端。利用該客戶端,我們可以用更容易的方式制作一個(gè)向服務(wù)器索取數(shù)據(jù)的請(qǐng)求,不需要去處理底層?$http API、HTTP方法以及URL。

把工作空間重置到第十一步

git checkout -f step-11

刷新你的瀏覽器或在線檢查這一步:Step 8 Live Demo

下面列出了第十步和第十一步之間最重要的區(qū)別。你可以在GitHub上看到完整的差異。

依賴性

Angular在ngResource模塊中提供了安靜的功能,它是與核心Angular框架分開分布的。

我們正在使用Bower以安裝客戶端依賴性。這一步更新的bower.json配置文件,以包含新的依賴性:

{
  "name": "angular-seed",
  "description": "A starter project for AngularJS",
  "version": "0.0.0",
  "homepage": "https://github.com/angular/angular-seed",
  "license": "MIT",
  "private": true,
  "dependencies": {
    "angular": "1.4.x",
    "angular-mocks": "1.4.x",
    "jquery": "~2.1.1",
    "bootstrap": "~3.1.1",
    "angular-route": "1.4.x",
    "angular-resource": "1.4.x"
  }
}

新的依賴性"angular-resource": "1.4.x"告訴bower安裝一個(gè)以angular為源的組件的版本,它與v1.4x版兼容。我們必須要求bower下載并安裝這個(gè)依賴性。我們可以通過(guò)運(yùn)行下面的指令來(lái)做到它:

npm install
**警告:**如果自從你上一次運(yùn)行`npm install`以后,Angular又發(fā)布了一個(gè)新版本,則你用`bower install`可能遇到問(wèn)題,因?yàn)槟惆惭b的angular.js的版本與它有沖突。如果你想通過(guò)它,則需要在運(yùn)行`npm install`之前先刪除你的`app/bower_components`文件夾。
**注意:**如果你已經(jīng)全局安裝了bower,則你可以運(yùn)行`bower install`,但是為了我們已經(jīng)預(yù)配置的項(xiàng)目,`npm install`為我們運(yùn)行了bower。

模板

我們的自定義源服務(wù)將被定義在app/js/services.js中,因此我們需要在我們的布局模板中包含這個(gè)文件。另外,我們還需要載入angular-resouces.js文件,它包含了ngResource模塊:

app/index.html.

...
  <script src="/attachments/image/wk/angularjs/angular-resource.js"></script>
  <script src="/attachments/image/wk/angularjs/services.js"></script>
...

服務(wù)

我們創(chuàng)建了自己的服務(wù),以提供對(duì)服務(wù)器上的手機(jī)數(shù)據(jù)的訪問(wèn):

app/js/services.js.

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

phonecatServices.factory('Phone', ['$resource',
  function($resource){
    return $resource('phones/:phoneId.json', {}, {
      query: {method:'GET', params:{phoneId:'phones'}, isArray:true}
    });
  }]);

我們使用模塊API,利用工廠函數(shù)注冊(cè)自定義的服務(wù)。我們傳入服務(wù)的名稱“Phone”以及工廠函數(shù)。工廠函數(shù)的結(jié)構(gòu)近似于控制器,兩者都可以聲明依賴性,以通過(guò)函數(shù)參數(shù)注入。Phone服務(wù)在$resource服務(wù)上聲明了一個(gè)依賴性。

$resource服務(wù)使它更容易只用寥寥幾行代碼創(chuàng)建一個(gè)RESTful客戶端。這種客戶端可以用在我們的應(yīng)用中,代替底層$http服務(wù)。

app/js/app.js.

...
angular.module('phonecatApp', ['ngRoute', 'phonecatControllers','phonecatFilters', 'phonecatServices']).
...

我們需要把phonecatServices模塊依賴性添加到phonecatApp模塊的需要數(shù)列中。

控制器

通過(guò)重構(gòu)掉底層的$http服務(wù),我們簡(jiǎn)化了我們的子控制器(PhoneListCtrlPhoneDetailCtrl),用稱為Phone的服務(wù)替代它。Angular的$resource服務(wù)比$http更容易使用,用來(lái)與作為REST的源對(duì)外提供的數(shù)據(jù)源交互?,F(xiàn)在我們更容易理解控制器中的這些代碼是干什么的了。

app/js/controllers.js.

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

...

phonecatControllers.controller('PhoneListCtrl', ['$scope', 'Phone', function($scope, Phone) {
  $scope.phones = Phone.query();
  $scope.orderProp = 'age';
}]);

phonecatControllers.controller('PhoneDetailCtrl', ['$scope', '$routeParams', 'Phone', function($scope, $routeParams, Phone) {
  $scope.phone = Phone.get({phoneId: $routeParams.phoneId}, function(phone) {
    $scope.mainImageUrl = phone.images[0];
  });

  $scope.setImage = function(imageUrl) {
    $scope.mainImageUrl = imageUrl;
  }
}]);

注意我們把PhoneList內(nèi)部替換成了什么:

$http.get('phones/phones.json').success(function(data) {
  $scope.phones = data;
});

換成:

$scope.phones = Phone.query();

我們通過(guò)這條簡(jiǎn)單語(yǔ)句來(lái)查詢所有手機(jī)。

一個(gè)需要注意的重要事情是,在上面的代碼中,在引用手機(jī)服務(wù)的方法的時(shí)候,我們沒有傳遞任何回調(diào)函數(shù)。雖然它看起來(lái)就像結(jié)果是同步返回的,但其實(shí)根本不是。同步返回的是一個(gè)“future”——一個(gè)對(duì)象,當(dāng)XHR響應(yīng)返回的時(shí)候,將填入數(shù)據(jù)。因?yàn)锳ngular中的數(shù)據(jù)綁定,我們可以使用這個(gè)future并且把它綁定到我們的模板上。然后,當(dāng)數(shù)據(jù)到達(dá)的時(shí)候,視圖將自動(dòng)更新。

有些時(shí)候,單憑future對(duì)象和數(shù)據(jù)綁定不足以滿足我們所有的需求,在那種情況下,我們可以添加一個(gè)回調(diào)函數(shù),以處理服務(wù)器響應(yīng)。PhoneDetailCtrl控制器通過(guò)設(shè)置回調(diào)函數(shù)中的mainImageUrl來(lái)演示它。

測(cè)試

因?yàn)槲覀儸F(xiàn)在使用了ngResource模塊,為了用以angular為源更新Karma配置單文件,它是必要的,這樣新測(cè)試才能通過(guò)。

test/karma.conf.js:

    files : [
      'app/bower_components/angular/angular.js',
      'app/bower_components/angular-route/angular-route.js',
      'app/bower_components/angular-resource/angular-resource.js',
      'app/bower_components/angular-mocks/angular-mocks.js',
      'app/js/**/*.js',
      'test/unit/**/*.js'
    ],

我們已經(jīng)修改了我們的單元測(cè)試,以驗(yàn)證我們的新服務(wù)會(huì)發(fā)起HTTP請(qǐng)求,并像預(yù)期那樣處理它們。測(cè)試還檢查了我們的控制器正確地與服務(wù)交互。

$resource服務(wù)參增加了帶有用來(lái)更新和刪除源的方法的響應(yīng)對(duì)象。如果我們打算使用標(biāo)準(zhǔn)的toEqual匹配器,我們的測(cè)試將失敗,因?yàn)闇y(cè)試值不能與響應(yīng)嚴(yán)格匹配。要想解決這個(gè)問(wèn)題,我們使用了一個(gè)新定義的toEqualData[Jasmine matcher][jasmine匹配器]。當(dāng)toEqualData匹配器對(duì)比兩個(gè)對(duì)象的時(shí)候,它考慮對(duì)象屬性屬性而忽略對(duì)象方法。

test/unit/controllersSpec.js:

describe('PhoneCat controllers', function() {

  beforeEach(function(){
    this.addMatchers({
      toEqualData: function(expected) {
        return angular.equals(this.actual, expected);
      }
    });
  });

  beforeEach(module('phonecatApp'));
  beforeEach(module('phonecatServices'));

  describe('PhoneListCtrl', function(){
    var scope, ctrl, $httpBackend;

    beforeEach(inject(function(_$httpBackend_, $rootScope, $controller) {
      $httpBackend = _$httpBackend_;
      $httpBackend.expectGET('phones/phones.json').
          respond([{name: 'Nexus S'}, {name: 'Motorola DROID'}]);

      scope = $rootScope.$new();
      ctrl = $controller('PhoneListCtrl', {$scope: scope});
    }));

    it('should create "phones" model with 2 phones fetched from xhr', function() {
      expect(scope.phones).toEqualData([]);
      $httpBackend.flush();

      expect(scope.phones).toEqualData(
          [{name: 'Nexus S'}, {name: 'Motorola DROID'}]);
    });

    it('should set the default value of orderProp model', function() {
      expect(scope.orderProp).toBe('age');
    });
  });

  describe('PhoneDetailCtrl', function(){
    var scope, $httpBackend, ctrl,
        xyzPhoneData = function() {
          return {
            name: 'phone xyz',
            images: ['image/url1.png', 'image/url2.png']
          }
        };

    beforeEach(inject(function(_$httpBackend_, $rootScope, $routeParams, $controller) {
      $httpBackend = _$httpBackend_;
      $httpBackend.expectGET('phones/xyz.json').respond(xyzPhoneData());

      $routeParams.phoneId = 'xyz';
      scope = $rootScope.$new();
      ctrl = $controller('PhoneDetailCtrl', {$scope: scope});
    }));

    it('should fetch phone detail', function() {
      expect(scope.phone).toEqualData({});
      $httpBackend.flush();

      expect(scope.phone).toEqualData(xyzPhoneData());
    });
  });
});

你現(xiàn)在可以在Karma選項(xiàng)卡中看到如下的輸出:

Chrome 22.0: Executed 5 of 5 SUCCESS (0.038 secs / 0.01 secs)

總結(jié)

現(xiàn)在我們已經(jīng)看到了如何建立一個(gè)自定義的服務(wù),作為REST的客戶端,我們已經(jīng)準(zhǔn)備好前往第十二步 應(yīng)用動(dòng)畫(最后一步)以學(xué)會(huì)如何用動(dòng)畫提高應(yīng)用程序。

以上內(nèi)容是否對(duì)您有幫助:
在線筆記
App下載
App下載

掃描二維碼

下載編程獅App

公眾號(hào)
微信公眾號(hào)

編程獅公眾號(hào)