Как подключить Angular.js к API бакенду

Illustration of a person sitting on the floor while leaning against a wall and looking at a tablet, with a spotlight effect highlighting them.
Обновлено: | Опубликовано:
Illustration of a person sitting on the floor while leaning against a wall and looking at a tablet, with a spotlight effect highlighting them.

В этой статье мы научимся соединять наше приложение с простым API при помощи библиотеки Restangular. Restangular – это популярная альтернатива встроенной в сам Angular.js библиотеки для работы с REST API. О её преимуществах над стандартной библиотекой хорошо рассказано на странице проекта на github: https://github.com/mgonto/restangular. Например, она поддерживает все HTTP методы и лишена различных неприятных багов встроенной в Angular.js библиотеки.

В качестве API мы будем использовать небольшое веб-приложение, написанное на фреймворке Sinatra, который написан на Ruby. Вам не нужно писать ruby код. Чтобы запустить API на вашей машине нужно выполнить следующие действия:

  1. Установите Ruby если у вас его ещё нет. В сети множество руководств на эту тему, в том числе на официальном сайте https://www.ruby-lang.org/en/
  2. Скачайте приложение git clone https://github.com/mkdev-me/sinatra-api-example
  3. Зайдите в папку с приложением и выполните команду bundle install
  4. После этого выполните rake db:create db:migrate
  5. И, наконец, запустите приложение командой ruby app.rb

Готово! Ваш маленький бакэнд готов к работе по адресу localhost:4567. Теперь мы можем обновить Angular.js приложение для работы с API.

Мы уже подключили Restangular на этапе настройки нашего приложения: вы можете увидеть его в списке зависимостей в файле bower.json. Более того, библиотека уже загружена как модуль, обратите внимание на эту строчку в src/app/index.js:

angular.module('ngmkdev', ['restangular', 'ui.router', 'ui.bootstrap'])

Поэтому мы можем перейти сразу к коду. В первую очередь нам необходимо задать базовый URL, используя который Restangular будет строить остальные ссылки. Для этого в библиотеке есть провайдер RestangularProvider, который мы можем использовать в блоке config в src/app/index.js:

// src/app/index.js
angular.module('ngmkdev', ['restangular', 'ui.router'])
  .config(function ($stateProvider, $urlRouterProvider, RestangularProvider) {

    RestangularProvider.setBaseUrl("http://localhost:4567");
    <  >
});

Основной ссылкой по-умолчанию будет ссылка на сервер с нашим API. Теперь обновим TransactionsStore так, чтобы он использовал данные с сервера. Добавим два новых метода: loadTransactions загрузит все данные с сервера, а addTransaction добавит новую транзакцию.

// src/components/transations_store.serve.js
angular.module('ngmkdev').factory('TransactionsStore', function(Restangular) {
  return {
    transactions: [],
    loadTransactions: function() {
      this.transactions = Restangular.all('transactions').getList().$object;
    },
    addTransaction: function(transaction) {
      var that = this;
      return Restangular.all('transactions').post({transaction: transaction}).then(function() {
        that.transactions.push(transaction);
      })
    },
    sum: function() {
      var sum = 0;
      this.transactions.forEach(function(el) {
        sum += parseFloat(el.amount);
      })
      return sum;
    }
  }
});

Обратите внимание на функцию then(). Она выполняется только тогда, когда завершился запрос на добавление транзакции. Подобный механизм называется promises, который является альтернативой привычному по jQuery механизму коллбеков. Отличие promise в том, что нам не нужно держать в памяти когда какой коллбек выполнится. Angular.js таким образом предоставляет гарантию, что если функция A завершила своё выполнение, то функция B выполнится (и только тогда, когда функция А действительно успешно выполнится).

В данном случае мы гарантируем, что массив транзакций обновится только после успешного сохранения новой транзакции на сервере. Чтобы сократить число запросов к серверу мы будем держать в памяти все транзакции и обновлять этот массив вручную, вместо того чтобы каждый раз получать все транзакции с сервера.

Большинство функций Restangular возвращают promise-объекты. Например, getList(), который мы используем для получения всех транзакций. Чтобы получить сами транзакции мы можем либо использовать then(), либо метод $object, который сразу вернёт нам все транзакции.

При помощи метода all() мы указываем с каким ресурсом работаем. Restangular сам догадывается, по каким ссылкам получать и отправлять данные, при условии что ваше API приложение соответствует REST стандартам. Таким образом, post() создаст новую запись, get() получит запись и т.п.

Код контроллера не претерпел больших изменений:

// src/app/main/transactions.controller.js
angular.module('ngmkdev').controller('TransactionsCtrl', function($scope, TransactionsStore) {

  TransactionsStore.loadTransactions();

  this.addTransaction = function() {
    TransactionsStore.addTransaction(this.newTransaction);
    this.resetTransaction();
  }

  this.resetTransaction = function() {
    this.newTransaction = {
      amount: 0.0,
      date: "1993-02-01",
      description: null
    }
  }
  this.transactions = TransactionsStore.transactions;
  this.resetTransaction();
});

Теперь все новые транзакции будут сохранены в базе данных и после перезагрузки страницы они никуда не пропадут.

Вы наверняка создали множество тестовых транзакций, чтобы посмотреть как всё работает. Теперь надо бы от них как нибудь избавиться. Коммит с изменениями: a0629f.

Домашняя работа:

  1. Добавьте и реализуйте кнопку удаления транзакции.


Это последняя статья курса по Angular.js. За 6 выпусков мы познакомились со всеми основными инструментами современной фронтенд разработки и, следуя лучшим практикам, написали полноценное приложение, работающее с бакендом через API. Полученные знания послужат отличным фундаментом для написания более сложных приложений на Angular.js. Пишите в комментариях что думаете об этой серии статей и как проходит ваше изучение и применение Angular.js.

Subscribe to our Newsletter

Let us send you the best of what we've discovered in DevOps, Cloud and Kubernetes, as well us occasional event announcements.

We are also preparing some ways to learn together: weekly challenges, free courses and more. Subscribe now to be the first to get those.