Trabalhando com serviços no Javascript

Trabalhando com serviços no Javascript

5 de agosto de 2016 0 Por Ramos de Souza Janones

Javascript é uma linguagem multiparadigma. Pode-se “emular” várias técnicas de programação com ele, e isso é incrível pois podemos decidir qual o melhor paradigma para a resolução dos problemas dos nossos projetos.

Porém se por um lado isso da um poder grandioso para a linguagem, também pode deixar os iniciados nela confusos, é muito comum escolher a abordagem errada para o problema.

Pensando nisso muitos desenvolvedores criam suas próprias soluções, uns pensando em ajudar outros em forçar padrões.
Eu prefiro ensinar a pescar, pois javascript não tem que ser complexo. Aversão 6 do javascript (ES6/ES2015) tornou a linguagem muito mais expressiva, facilitando muito o entendimento.


Encapsulando lógicas

Tudo em javascript são objetos (exceto undefined), então serviços também são objetos, dominando como criamos e trabalhamos com objetos todas as coisas ficam bem mais tranquilas.

 

Scope e Closures

Javascript possui escopo léxico. Entre outras coisas isso permite que você crie closures.
De maneira resumida você cria um “ambiente controlado” onde há funções/variáveis que só podem ser acessadas naquele escopo, criando um enclausuramento (closure).

const initPage = (root) => {
  const $root = $(root);
  const $menu = $menu.find('.menu');
  const $profile = $menu.find('.profile');

  const initProfile = () => {
    $.get('/me')
     .then(response => {
       $profile.text(response.username);
     });
    //  ...
  };

  const showProfileModal = e => {
    // ...
  };

  $profile.on('click', e => showProfileModal(e));

  initProfile();
};

initPage('body');
 

Este é um exemplo bem bobo, mas que ilustra bem como criamos closures.
As variáveis declaradas dentro de initPage só existem naquele escopo.
No mesmo exemplo podemos refatorar esse código em uma IIFE (Immediately-Invoked Function Expression)

((root) => {
  const $root = $(root);
  const $menu = $menu.find('.menu');
  const $profile = $menu.find('.profile');

  const initProfile = () => {
    $.get('/me')
     .then(response => {
       $profile.text(response.username);
     });
    //  ...
  };

  const showProfileModal = e => {
    // ...
  };

  $profile.on('click', e => showProfileModal(e));

  initProfile();
})('body');
 

Nesse código declaramos uma função e a executamos imediatamente, passando um argumento. Isso é extremamente útil quando queremos fazer um processamento de uma informação que vai servir apenas para criar uma variável.

const timezones = (() => {
  const zones = [];
  const min = -12;
  const max = 13;
  let simbol;

  for (let i = min; i <= max; i++) {
    simbol = (i < 0) ? '' : '+';
    zones.push(`GMT${simbol}${i}`);
  }

  return zones;
})();
 

Aprenda React do Zero ao ProfissionalComo você já pode perceber, é possível expor dados de uma closure como no exemplo anterior. A variável zones é retornada, assim a variável timezonesagora possui como valor o resultado da closure.
Nesse exemplo a closure não usa dados externos a ela (parent scope/escopo pai) porém dada a natureza do javascript isso é perfeitamente possível.

Isso é útil para não poluir o escopo principal com informações irrelevantes.

const makeCounter = (start = 0) => {
  let current = start;

  const add = (value = 1) => current += value;
  const remove = (value = 1) => add(value * -1);
  const get = () => current;

  return { add, remove, get };
};

const counter = makeCounter(10);

counter.add() // 11
counter.add() // 12
counter.add(8) // 20
counter.remove(10) // 10
 

Este é um exemplo bem interessante. Estamos combinando closures comfactory.
Com isso podemos criar vários contadores, e trabalhar como melhor convir com estes contadores.

 

Só isso! Simples, né?

Se você entendeu como o exemplo do contador funciona, parabéns você já sabe criar serviços com javascript.
Isso mesmo, este contator é um serviço. Na verdade ele é um factory, mas com pequenos ajustes ele vira um serviço de fácil reuso.

const makeCounter = (start = 0) => {
  let current = start;

  const add = (value = 1) => current += value;
  const remove = (value = 1) => add(value * -1);
  const get = () => current;

  return { add, remove, get };
};

export default makeCounter
 
factory
import makeCounter from './makeCounter.js';

export default makeCounter(0);
 
counter service

Agora temos dois arquivos, um contendo o factory do contador, e outro contendo o serviço de contagem.

Módulos javascript

 

Como visto anteriormente, é bem simples criar serviços com javascript, basta antes entender alguns conceitos.

Porém isso não é tudo, se você esta criando um serviço é porque tem a intenção de reusar esta lógica em mais de um local da aplicação. Isto não é uma regra, talvez você queira apenas centralizar a lógica da operação.

Não importa o objetivo inicial, você vai acabar criando um módulo javascript para aquela sua operação/serviço. No exemplo do contador foram criados dois arquivos, o contador e o factory do contador. Nesse momento você precisa entender minimamente o que são módulos javascript.

Em resumo: um arquivo javascript é um módulo e um módulo javascript é um arquivo.

Você pode criar um módulo a partir de outros módulos, como é o exemplo do contador, ele é composto a partir do módulo makeCouter.

Em geral a lógica dos módulo é encapsulada em closures e o retorno delas écacheado, sendo assim, uma vez que você importa um módulo, ele será omesmo sempre, compartilhando seu estado. Saiba mais aqui.

Usando serviços

Agora que você possui essas informações acredito que criar seus próprios serviços não será nenhum bicho de sete cabeças.

Vale a pena dizer que tudo pode ser considerado um serviço, inclusive factories.

Para reforçar vou deixar mais um exemplo de uso de serviços.

import Http from './http.js';
import UsersService from './modules/users/service.js';

Http.setToken('XPTO'); // Define o token de autentificação

// Cattega a primeira página de usuários
// Exibe um alerta com o nome do primeiro usuário retornado pelo serviço

UsersService
  .getAll({ page: 1 })
  .then(result => result.data)
  .then(data => data[0])
  .then(first => {
    alert(first.name);
  });
 

Para efeito de aprendizado uma sintaxe alternativa, com import binding.

import { setToken } from './http.js';
import { getAll as getAllUsers } from './modules/users/service.js';

setToken('XPTO'); // Define o token de autentificação

// Cattega a primeira página de usuários
// Exibe um alerta com o nome do primeiro usuário retornado pelo serviço

getAllUsers({ page: 1 })
  .then(result => result.data)
  .then(data => data[0])
  .then(first => {
    alert(first.name);
  });
 

Este pode não parecer para alguns mas é um exemplo bem prático do uso de serviços.
O serviço de Http também é usado pelo serviço de usuários, por isso é possível definir o token de autentificação antes de efetivamente usar os serviços, pois eles vão compartilhar o mesmo estado/serviço.

Outra característica interessante é que esses serviços não estão ligados diretamente a nenhum contexto. Isso significa que não importa que ambiente você esteja ou que framework você esta usando, os serviços são agnósticos. Eles podem ser usados no NodeJS, VueJS, ReactJS, etc.
Este é um dos princípios do polimorfismos do javascript… porém este é outro assunto.


Caso queira aprender mais sobre scopes e closures veja a série de vídeos Domine this do Codecasts, lá você também terá acesso a uma série de vídeos sobre ES6.

Ramos de Souza Janones

Janones, é um empreendedor brasileiro apaixonado por empreendedorismo e tecnologia. Ao longo dos anos trabalhando com o desenvolvimento de softwares desktop desde a linguagem Clipper, passando pelo Delphi e atualmente com Java.

Optou pela formação de Publicidade e Marketing por sua segunda empresa de tecnologia ter participado do "boom" da internet nos anos 90 e na procura de melhorar seus conhecimentos em negócios.

Em razão da principal formação e profundos conhecimentos em programação e banco de dados, é capaz de realizar o desenvolvimento de aplicativos web, desktop e mobile com maior criatividade e inovação que profissionais de desenvolvimento com uma formação única e mais especifica, dedicada somente ao desenvolvimento de softwares.

Com toda sua experiência com empresas de software, sua formação e paixão por negócios escreveu o livro "Marketing para Empresas e Profissionais de Software", publicado pela editora carioca Ciência Moderna em 2012. Além de outros livros sobre programação.
LEIA TAMBÉM:  CoffeeScript, TypeScript, JavaScript e o AngularJS 4