AngularJs Done Right!



AngularJs Done Right!

0 1


angular-done-right

Angular best practices slides done with reveal.js

On Github rfviolato / angular-done-right

AngularJs Done Right!

by Rafael Violato

Assuntos

  • Services
  • Dependency Injection
  • Fat Model, skinny Controller
  • Promises e $q

Services

Services, Factories e Providers

Quando utilizar cada um?

Service

  • Um service é uma função construtora
  • Por trás dos panos é feito um new nesta função
  • Você recebe uma nova e única instância
  • Semelhantes a classe do ES6
angular.module('awesomeApp')
       .service('myService', service);

function service(){

    this.something = 'something';
    this.sum = sum;

    function sum(a, b) {
        return a + b;
    }
}

Factory

  • Você recebe a referência da função
  • A função é executada, e o que é injetado é o que foi retornado
  • Por isso permite maior nível de configuração (código antes do return)
  • Possibilidade de criar quantas instâncias desejar
angular.module('awesomeApp')
       .factory('myFactory', factory);

function factory(){

    var something = 'something';

    var factory = {
        something: something,
        sum: sum
    };

    return factory;

    function sum(a, b) {
        return a + b;
    }
}

Provider

  • Service com maior nível de configuração
  • Requer que exponha-se uma função $get que funcionará como service
  • Permite configuração na fase de config do módulo através de métodos e variáveis fora do $get
  • $get funciona como um factory
angular.module('myApp')
  .provider('myProvider', provider);

function provider() {
  this.configVar = 'This is a config var';
  this.$get = $get;

  function $get() {
    var serviceVar = 'This is a service var';

    var factory = {
      serviceVar: serviceVar
    };

    return factory;

  }
}

Dependency Injection

Como funciona?

  • Quando você declara uma estrutura injetável, o $provide é chamado no config do seu módulo
  • Cada estrutura definida (Ex.: .service(...), .factory(...), etc...) são atalhos para chamadas dos métodos respectivos no $provide
  • O $inject é o resposável de injetar estes services em qualquer função ou estrutura de dado
  • $inject.get() busca pelo service e devolve a função
  • $inject.invoke() é responsável por deixar o service disponível em qualquer função
  • O angular utiliza um invoke para cada requisição de injeção

Fat Model, skinny Controller

Que porra é essa?

  • Fazer teu model em Services
  • Controller recebe as injeções de model
  • Abstrair toda lógica para o model
  • Goodbye $scope!

Vantagens

  • Possui um model somente pelo pattern singleton dos services
  • Menos copy/paste
  • "Métodos Globais"
  • Mais simples de testar
  • Injeta o model em qualquer estrutura
  • Independe da hierarquia de $scope
  • Somente uma "fonte da verdade"
  • Mais próximo do Angular 2

Code Time

Promises no angular

$http

  • É um service do Angular
  • Retorna uma promise
  • Tradicionalmente é um GET porém aceita todos os comandos comums de http request (ex.: PUT, DELETE, etc...)
  • Métodos para tratar promise: then, catch, success, error e finally
angular.module('awesomeApp')
       .factory('myService', service);

service.$inject = ['$http'];

function service($http){
    var service = {
        getData: getData
    };

    return service;

    function getData() {
        return $http('http://api.pagar.me/1/transactions');
    }
}

O "dólar quê"

$q

  • Promises customizáveis
  • Formato semelhante a promise do ES6
angular.module('awesomeApp')
       .service('myService', service);

service.$inject = ['$q', '$timeout'];

function service($q, $timeout) {
    var self = this;

    this.wait = wait;
    this.done = false;

    function wait() {
        var promise = $q(function(resolve, reject) {
            $timeout(resolve, 1000);
        });

        promise.then(success, error);
    }

    function success() {
        self.done = true;
    }

    function error() {
        self.done = false;
    }
}

controllerAs

  • Consegue utilizar a função do controller como model
  • Convenção: var vm = this;
  • Desta forma o conseguimos de vez deixar o $scope de lado como model
  • Pode estabelecer o namespace no controllerAs na rota ou na diretiva ng-controller

Mas pra quê?!

  • Adiciona um namespace aos dados
  • Favorece leitura do código
  • Resolve problema de nested controllers
  • Abandona $scope
angular.module('awesomeApp')
       .controller('myController', controller);

controller.$inject = ['myService'];

function controller(myService){

    var vm = this;

    myService.getData()
        .then(success, error);

    function success(promiseData) {
        vm.data = promiseData;
    }

    function error() {
        console.error('Oh Fuck!');
    }

}
<div ng-controller="myController as ctrl">
    <ul>
        <li ng-repeat="item in ctrl.data"></li>
    </ul>
</div>

Bora juntar o que aprendemos

Como utilizar estes conceitos juntos?

  • Utilize providers para services com pré configuração
  • Concentre toda sua lógica no model (services)
  • Para dados assíncronos, utilize promises nos models
  • Injete o model em qualquer estrutura que necessitar dele
  • Através do controllerAs, exponha os dados para a view
  • Utilize $scope somente para $watchers, $scope events e alguns métodos específicos ($apply, $parse, $eval, etc...)

Code Time

Para estudar

Criar aplicações utilizando fat-model skinny-controller https://scotch.io/tutorials/making-skinny-angularjs-controllers Styleguides John Papa e Todd Motto http://nomadev.com.br/angularjs-promises-promessas-o-guia-definitivo/ https://github.com/angular/angular.js/wiki/Understanding-Dependency-Injection
AngularJs Done Right! by Rafael Violato