Node.js: monitorando APIs RESTful com o Application Insights

Dando continuidade aos meus artigos sobre Node.js no Azure, hoje eu irei demonstrar como monitorar uma API RESTful desenvolvida em node com TypeScript, utilizando o Application Insights.

Para aqueles que estão tendo o seu primeiro contanto com Application Insights nesse artigo, ele é um serviço de monitoramento de aplicações do Azure.

Com ele nós conseguimos medir a performance das nossas aplicações, extrair métricas de acesso por um range de tempo, detectar falhas … etc.

A ideia desse artigo será demonstrar como monitorar uma API RESTful desenvolvida em Node.js com TypeScript. Para isso, eu irei utilizar um gerador de APIs que eu desenvolvi utilizando essas tecnologias.

Caso tenha interesse em utilizar esse mesmo projeto, segue o seu link no portal NPM gerador-ts-api, e um vídeo passando alguns detalhes sobre essa estrutura:

Com o projeto OK, para os próximos passos será necessário ter uma conta no Azure. Caso você ainda não tenha uma, a Microsoft tem um programa chamado Visual Studio Dev Essentials que disponibiliza alguns benefícios como: créditos para serem utilizados no Azure, Visual Studio, acesso grátis por um período na Pluralsight… etc.

Caso tenha interesse em saber um pouco mais sobre esse programa, eu recomendo a leitura do seguinte artigo: Visual Studio Dev Essentials (Free).

Com o projeto criado e a sua subscription OK, vamos agora criar um novo serviço no Azure para monitorar a nossa aplicação. Para isso, acesse a sua conta, vá até-> Create resource -> Devops -> Application Insights e clique no botão Create.

Na próxima tela será necessário informar os dados da sua aplicação como: Nome, Resource Group … etc. Abaixo você tem uma imagem demonstrando como eu preenchi essa etapa para um evento presencial aqui em SP:

Clique em Create e aguarde a tela informando que o seu deploy está completo. Abaixo você tem uma imagem demonstrando essa etapa:

Agora clique no botão Go to resource -> vá até Overview e copie a sua instrumental Key:

Essa chave que irá vincular a nossa aplicação ao serviço no Azure.

Com a Key criada, vamos agora adicionar ela na nossa aplicação. Para isso, abra o seu projeto e siga os passos abaixo:

O primeiro passo será importar a biblioteca do applicationinsights para o nosso projeto. Para isso, abra um terminal, navegue até o seu projeto e execute o comando abaixo:

npm i applicationinsights --save

E no caso de estar seguindo esse passos em um projeto com TypeScript:

npm i @types/applicationinsights --save-dev

Agora abra o arquivo de inicialização do seu projeto, chame a biblioteca importada no passo anterior, em seguida inicialize ela com a sua instrumental Key:

const appInsights = require('applicationinsights'); 

appInsights.setup('<instrumentation_key>').start();

Caso esteja seguindo esses passos em um projeto gerado pelo o gerador-api-ts acima, basta abrir o arquivo startUp.ts e adicionar as linhas abaixo nele:

import * as appInsights from 'applicationinsights';
 // no inicio do arquivo
appInsights.setup('<instrumentation_key>').start();
 // no método middler

Monitorando a aplicação

Agora para que possamos monitorar a nossa aplicação, será necessário executar ela e abrir o serviço no Azure. Como eu estou utilizando a API gerado com o gerador mencionado acima, basta executar o comando npm run compile para gerar o dist do projeto e npm start para subir a aplicação.

Com o projeto rodando, vamos simular uma falha, uma chamada a uma rota/endpoint que não existe como por exemplo http://localhost:3050/api/v1/news.

Depois de alguns segundos acessando o portal conseguimos pegar o erro na chamada:

Como eu passei no inicio do artigo, nós podemos pegar métricas de acesso, performance … etc da nossa aplicação. Abaixo você tem um print demonstrando a performance da aplicação que eu estou utilizando nesse artigo:

Caso você tenha interesse em ver como retirar as outras métricas, como esse serviço funciona mais a fundo, eu recomendo a leitura do seguinte link na documentação da Microsoft: App-insights-overview.

Bom era isso pessoal, espero que tenham gostado e até um próximo artigo galera 😉

Conheça o Phaser.JS, uma biblioteca de criação de jogos JavaScript

Você conhece a biblioteca Phaser.JS para criação de jogos em JavaScript?

Phaser é uma biblioteca para criação de jogos que foi idealizada pela Photon Storm. Com ela, podemos criar jogos que rodam tanto em ambiente mobile quanto desktops. Ela roda nos principais navegadores atuais de desktop. Em dispositivos móveis, é suportado no Chrome mobile, no navegador Safari (no IOS5 para cima). Acesse a biblioteca: phaser.io

Principais recursos:

O Phaser não utiliza nenhuma prática interna de orientação a objeto, não possui heranças de código e componentes. Mas você pode alterar as funções do Phaser.

Para renderização de gráficos, o Phaser utiliza o Pixi.js. Nos jogos, se o navegador suportar WebGL, o usuário terá uma melhor experiência. Os jogos em HTML5 caminham para o futuro de WebGL disponível em dispositivos móveis. Para isso acontecer, é apenas uma questão de tempo.

O carregamento do Phaser suporta:

  1. Imagens;

  2. Sprite Sheets;

  3. Texture Atlases;

  4. Arquivos de áudio;

  5. Arquivos de dados;

  6. Arquivos JavaScript;

  7. Tilemaps;

  8. Fontes Bitmap.

Áudio:

Com a WebAudio API, podemos ter uma integração apropriada de áudio, com múltiplas rotas, canais e os mais variados tipos de efeitos.

Inputs:

Multi-Touch, Keyboard, Pointer e Mouse: O Phaser suporta os mais variados tipos de inputs, como toques na tela, cliques de mouse, teclas pressionadas, entre outros.

Continue lendo “Conheça o Phaser.JS, uma biblioteca de criação de jogos JavaScript”

Angular 8.0

Veja nesse artigo as principais novidades dessa nova versão do Angular.

Já faz um tempo que eu estou brincando com essa versão do Angular em RC. Eu atualizei o meu ambiente para essa versão para testar a nova versão do TypeScript e indo já indo para primeira novidade do Angular 8, nesse update nós podemos trabalhar com o TS na versão 3.4 😉

Caso você não tenha visto nada dessa nova versão do TS 3.4, eu recomendo a leitura dos seguintes links abaixo:

E indo para a próxima novidade, nessa versão foi removido o pacote @angular/http. Esse pacote estava deprecated desde de a versão 5.0, desde de essa versão nós deveríamos estar utilizando o pacote @angular/common/http.

Novidades nos Forms

markAllAsTouched

Nessa versão foi adicionado um novo método dentro da class AbstractControl chamado markAllAsTouched. Esse método é parecido com o markAsTouched das versões anteriores, a diferença é que esse método marca todos controles do nosso form como touched.

Sintaxe

form.markAllAsTouched();

Caso você tenha interesse em saber mais sobre AbstractControl, eu recomendo a leitura do seguinte do seguinte link: Angular-AbstractControl.

clear

Para o pessoal que já trabalha com o Angular a um tempo, com certeza já deve ter feito algo como no exemplo abaixo para limpar um form.

while (formArray.length) {
  formArray.removeAt(0);
}

Nessa versão nós podemos utilizar o .clear() para limpar todos elementos de uma só vez 😉

Sintaxe

formArray.clear()

Rotas

Nessa versão foi adicionado uma nova sintaxe para declaração de rotas com lazy-loading.

Agora ao invés de declaramos assim:

loadChildren: './news/news.module#NewsModule'

Nós declaramos com o import:

loadChildren: () => import('./races/races.module').then(m => m.RacesModule)

Essa sintaxe com import() já é utilizada nas versões anteriores do TypeScript.

Ivy

Essa sem dúvidas foi uma das atualizações mais esperadas. Eu estou escrevendo um artigo focando nele, mas caso esse seja o seu primeiro contato com ele, o Ivy é o novo compilador do Angular 😉

Bom galera, esse foi um post rápido com foco em alguns dos updates dessa nova versão.

Referências

alligator.io

Node.js: importando dados de um arquivo .csv para o mongoDB

Quem nunca precisou abrir arquivo para importar o seus dados para uma base de dados? Esse é um processo simples que ajuda muito outras equipes como de RH, Financeiro … etc.

Hoje eu irei demonstrar como importar dados de um arquivo .csv com algumas das batalhas que ocorreram na serie GOT (Game of Thrones), utilizando o Node.js e uma base de dados mongoDB.

Para pular a etapa de criação de um novo projeto eu irei utilizar a versão final desse artigo. Caso tenha interesse em clonar esse projeto, segue o seu link no meu GitHub: node-csv-mongodb.

O projeto está bem simples, abaixo você tem uma breve explicação de cada um dos arquivos utilizados.

Analisando ela nós temos:

  • config/db: arquivo de conexão com a nossa base de dados
  • models/battles.js: model contendo os campos do arquivo .csv
  • repository/battleRepository: arquivo de mapeamento da model com a collection do banco de dados
  • battles.csv: arquivo contendo algumas das batalhas que ocorreram na série GOT
  • index.js: nós iremos explorar esse arquivo melhor, mas por hora ele é o responsável por abrir o arquivo .csv e importar os dados para o nosso banco de dados

Abra o projeto no seu editor de textos preferido, em seguida adicione a sua string de conexão no arquivo db.js. Com essa etapa OK, vamos analisar o arquivo index.js:

const db = require('./config/db');
const battleRepository = require('./repository/battleRepository');

const csv = require('csv-parser');
const fs = require('fs');

fs.createReadStream('./battles.csv')
    .pipe(csv())
    .on('data', (row) => {
        battleRepository.create(row);
    })
    .on('end', () => {
        console.log('CSV file successfully processed')
    });

Analisando esse trecho de código nós temos:

  • 01: estamos importando o arquivo db.js com a nossa conexão com o db
  • 02: estamos importando o nosso repository, ele será responsável pelas nossas queries.
  • 04 e 05: importando os pacotes (fs) e (csv-parser) para manipularmos o arquivo .csv
  • 07 até a 14: estamos passando o caminho do arquivo que iremos manipular -> abrindo ele -> passando os dados para o método .create do nosso repository para ele salvar os dados no db, assim que ele finalizar irá retornar a mensagem: ‘CSV file successfully processed’.

Para ficar mais clara essa etapa, comente a linha 11 do arquivo e adicione um console.log(row); no lugar, em seguida execute o comando node index.js. Abaixo você tem uma imagem demonstrando esse passo:

Note que ele passa por cada uma das linhas do arquivo e retorna cada uma deles na row. Agora descomente a linha 11 e execute o comando node index.js novamente.

Para verificar se os dados foram importados corretamente, eu irei utilizar o Robo 3T para conectar na minha base de dados. Abaixo você tem uma imagem demonstrando esse passo:

Note que todos os arquivos formam importados corretamente.

Bom, a ideia desse artigo era ser algo rápido para demonstrar como importar um arquivo .csv em um banco de dados mongoDB.

Espero que tenham gostado e até um próximo artigo pessoal.

RabbitMQ criando workers com Node.js

Introdução

Dando continuidade a minha serie de artigos sobre RabbitMQ, hoje irei apresentar uma de suas formas de implementação, os workers. Caso tenha interesse em saber um pouco mais sobre os Workers ou ler os primeiros artigos dessa série, eu recomendo a leitura dos artigos abaixo:

Para que você possa ter um melhor entendimento, eu irei criar um exemplo utilizando o Node.js e o RabbitMQ dentro de um container Docker.

O primeiro passo é ter o RabbitMQ instalado, como mencionado acima eu irei utilizar o RabbitMQ dentro de em um container Docker. Caso você ainda não tenha esse ambiente, eu recomendo a leitura do segundo link que eu passei acima, la eu demonstro como criar esse ambiente.

Criação do projeto

Abra um terminal no seu computador, em seguida escolha um local para criação do seu projeto. Navegue até ele via terminal e execute o comando abaixo:

npm init -y

Esse comando irá inicializar o seu projeto criando um arquivo chamado package.json. Agora vamos baixar o pacote do RabbitMQ. Para isso, execute o comando abaixo no seu terminal:

npm install amqplib --save

Com o projeto criado e a biblioteca do amqplib importada, vamos criar dois novos arquivos no nosso projeto.

O primeiro será o arquivo da nossa aplicação, para esse artigo eu irei chamar ele de app.js. Crie ele na raiz do seu projeto, em seguida atualize ele com o trecho de código abaixo:

var amqp = require('amqplib/callback_api');

amqp.connect('amqp://localhost:5672', function (err, conn) {
    conn.createChannel(function (err, ch) {
        var q = 'hello';
        var msg = 'Hello World 123!';
        ch.assertQueue(q, { durable: false });     
        ch.sendToQueue(q, new Buffer(msg));
        console.log(" [x] Sent %s", msg);
    });
    setTimeout(function () { conn.close(); process.exit(0) }, 500);
});

Analisando o código acima você tem:

Agora vamos criar os nossos Workers. Para isso, crie um novo arquivo chamado worker.js na raiz do seu projeto e atualize ele com o seguinte trecho de código:

var amqp = require('amqplib/callback_api');

amqp.connect('amqp://localhost:5672', function (err, conn) {
    conn.createChannel(function (err, ch) {
        var q = 'hello';

        ch.assertQueue(q, { durable: false });
        ch.prefetch(1);
        console.log(" [*] Waiting for messages in %s. To exit press CTRL+C", q);
        ch.consume(q, function (msg) {
            console.log(" [x] Received %s", msg.content.toString());
        }, { noAck: true });
    });
});

Analisando esse código você tem:

Testando o código

Agora para testar o nosso código, abra 3 terminais no seu computador, navegue até o seu projeto e siga os passos abaixo:

Terminal 01

Execute o comando abaixo para criar o seu primeiro worker:

node worker.js

Terminal 02

Execute o comando abaixo para criar o seu segundo worker:

node worker.js

Terminal 03

Execute o comando abaixo para criar a sua aplicação e enviar a primeira mensagem para sua fila.

Obs.: O RabbitMQ trabalha com o conceito de Round Robin, logo o worker 1 pode não ser o primeiro a consumir a sua fila

node app.js

Abaixo você tem um vídeo demonstrando esse passo:

O intuito desse artigo foi demonstrar como trabalhar com os Workers do RabbitMQ utilizando o Node.js. Caso tenha interesse em baixar o código desenvolvido nesse artigo, segue o seu link no meu GitHub: Node-RabbitMQ-Workers.

Espero que tenham gostado e até um próximo artigo pessoal.

Conheça MelonJS, a biblioteca para criação de jogos JavaScript

Você conhece a biblioteca melonJS para criação de jogos em HTML5 e JavaScript?

Conheça o MelonJS, um mecanismo de desenvolvimento de jogos em HTML5 que capacita desenvolvedores e designers a se concentrarem no conteúdo.

A biblioteca fornece uma coleção de entidades compostas e suporte para ferramentas de terceiros, dando-lhe ima combinação poderosa que pode ser usada por atacado ou fragmentada.

O melonJS possui os seguintes recursos:

  • Um novo e leve mecanismo baseado em sprites 2D;
  • Biblioteca autônoma (não depende de mais nada, exceto de um navegador compatível com HTML5);
  • Compatível com a maioria dos principais navegadores (Chrome, Safari, Firefox, Opera, IE) e dispositivos móveis;
  • Renderização rápida de Canvas e WebGL em computadores e dispositivos móveis;
  • Resolução de alta DPI e dimensionamento automático de tela;
  • Suporte de áudio HTML5 multicanal e Web Audio em dispositivos suportados;
  • Leve implementação físic, garantindo baixos requisitos de cpu;
  • Algoritmo de colisão baseado em polígono (SAT) para detecção e respostas precisas;
  • Detecção rápida de colisão de fase ampla, usando particionamento espacial;
  • Suporte a ferramentas de terceiros para definição de corpo físico (PhysicEditor, Physic Body Editor);
  • API de matemática avançada para vetor e matriz;
  • Efeitos de interpolação;

Continue lendo “Conheça MelonJS, a biblioteca para criação de jogos JavaScript”

Duas maneiras de unir vetores em JavaScript:

Você sabe como unir vetores?

Este artigo mostrará duas maneiras de unir vetores e retornar um novo vetor.

Serão utilizados os operadores Spread e Concat.

// Duas formas de unir vetores
const circ = [‘círculo’, ‘esfera’];
const quadr = [‘quadrado’, ‘cubo’];

// Usando o Concat para unir os vetores:
cons unirVet = [].concat(circ, quadr);

// Usando o Spread para unir os vetores:
const unirSpread = [...circ, ...quadr];

// E o resultado será:
console.log(unirSpread);

// [‘círculo’, ‘esfera’, ‘quadrado’, ‘cubo’]

Você também pode escrever o método Concat deste modo:

const circ = [‘círculo’, ‘esfera’];
const quadr = [‘quadrado’, ‘cubo’];

const unirVetor = circ.concat(quadr);
console.log(unirVetor);

E o resultado será:
// [‘círculo’, ‘esfera’, ‘quadrado’, ‘cubo’]

console.log(circ); // [‘círculo’, ‘esfera’];
console.log(quadr); // [‘quadrado’, ‘cubo’];

Este modo não altera o vetor existente.

Comparando os dois modos do concat:
// Versão 1
cons unirVet = [].concat(circ, quadr);

// Versão 2
const unirVetor = circ.concat(quadr);

A versão 1 cria uma nova matriz e não manipula uma matriz existente. Visualmente falando, a versão 2 parece adicionar a matriz de quadrados à matriz de círculos.

A diferença entre Spread e Concat:

Spread:

O Spread quebra um array ou uma string em múltiplos elementos. Se você possui um array e quer criar um array com o existente fazendo parte dele, você pode usar o Spread.

let umaString = "Olá Mundo";

console.log(umaString); // exibe a string

console.log(...umaString); // exibe cada caracter

let umVetor = [11,22,33,44,55,66]; //cria um vetor

console.log(umVetor); // mostra conteúdo o vetor

console.log(...umVetor); // mostra o conteúdo de cada índice do vetor

Concat:

Já o Concat cria um novo vetor unindo os elementos que foram passados como parâmetro, não alterando a si mesmo ou aos argumentos passados, mas criando um novo vetor contendo uma cópia de si e dos argumentos.

A cópia é uma referência aos objetos. Se o objeto original for modificado, as mudanças serão visíveis no original e na cópia.

Strings e numbers (diferente dos objetos String e Number), o concat copia os valores de strings e numbers para o novo vetor, mas qualquer alteração no novo vetor não refletirá no original.

// Cria uma função que concatenará
// o vetor e a variável
function combinaVetor(vetor1, vetor2){ 
    return [].concat(vetor1, vetor2);
} 

// Crie um vetor
const ehVetor = ['carro', 'moto', 'onibus'];

// Crie uma variável
const notVetor = 7;

// Chamada da função
combinaVetor(ehVetor, notVetor);

// [“carro”, “moto”, “onibus”, 7]

Unindo arrays com Push:

Quando você utilizar o método Push, você não criará um novo array, mas sim manipulando um existente:

const meninos = ["joao", "josé"];
const meninas = ["maria", "vanessa"];
const alunos = meninos.push(...meninas);

console.log(alunos); //Quando você usa o push, ele retornará o tamanho do vetor unido.
console.log(meninos); 
["joao", "josé", "maria", "vanessa"] // Retorna o vetor meninos modificado 

console.log(meninas);
 ["maria", "vanessa"]

Gostou deste artigo? Comente abaixo e compartilhe com seus amigos!

Como criar um cartão de crédito com a biblioteca Card

Você já conhece a biblioteca Card criada por Jesse Pollak?

Esta biblioteca auxilia você a criar um cartão de crédito utilizando poucas linhas de código. Com ela, você possui acesso aos mais variados tipos de cartão de crédito, e consegue visualizar em tempo real as informações sendo inseridas no cartão, alterando seus dados conforme você digitar. Tudo nesta biblioteca foi criado com CSS, HTML e JavaScript puro, e não necessita de imagens adicionais.

A biblioteca reconhece diversas formas de cartão de crédito e você não precisa alterar nada (além dos dados a serem inseridos no cartão). Com ela, você terá uma pré-visualização em tempo real do seu cartão.

Usando sem jQuery:

Para utilizar a biblioteca Card, você precisará incluir o arquivo card.js no seu HTML. Não será necessário um link para o CSS, porque o arquivo JavaScript já fará isso por você.

<!-- no final do BODY -->
<!-- CSS está incluso no arquivo JavaScript -->
<script src="/path/to/card.js"></script>

Assim que você incluir este arquivo, poderá inicializar o Card.

let cartao = new Card({
    // seleciona a classe #formCard
    form: '#formCard', 
    // seleciona o container que mostra
    // o cartão na tela
    container: '.card-wrapper',

Instalando a biblioteca Card por bower:

Se você está usando o bower, poderá instalar o card.js com este comando:

bower install card --save

Se você está usando npm, você poderá instalar o card.js assim:

npm install --save card

Criando os campos de preenchimento do cartão:

O cartão renderiza com espaços reservados para cada campo de preenchimento: número do cartão, nome, validade e cvc.

<form id="formCard">
    <div>
        <input type="text" name="number" placeholder="Numero Cartão" />
        <input type="text" name="name" placeholder="Nome" />
    </div>
    <div>
        <input type="text" name="expiry" placeholder="Data" />
        <input type="text" name="cvc" placeholder="CVC" />
    </div>
    <div>
        <input id="bt" type="submit" value="Enviar" />
    </div>
</form>

Criando um cartão:

let cartao = new Card({
    form: '#formCard',
    container: '.card-wrapper',
    // Altera o placeholder
    placeholders: {
        name: 'Seu nome aqui'
    }
});

Para traduzir o cartão para sua língua nativa, você pode alterar adicionando os objetos a seguir:

// Altera o placeholder
placeholders:{
    name: 'Seu nome aqui'
}
messages: {
    validDate: 'Data\nexpiração',
    monthYear: 'mes/ano',
},
O código deverá ficar assim:
<!DOCTYPE html>
<html lang="pt-br">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <title>Biblioteca Card</title>
</head>
<body>
    <script src="card-master/dist/card.js"></script>
    <div class='card-wrapper'></div>
    <form id="formCard">
        <div>
            <input type="text" name="number" placeholder="Numero Cartão" />
            <input type="text" name="name" placeholder="Nome" />
        </div>
        <div>
            <input type="text" name="expiry" placeholder="Data" />
            <input type="text" name="cvc" placeholder="CVC" />
        </div>
        <div>
            <input id="btn" type="submit" value="Enviar" />
        </div>
    </form>
    <script>
        let cartao = new Card({
            form: '#formCard',
            container: '.card-wrapper',
            // Altera o placeholder
            placeholders: {
                name: 'Seu nome aqui'
            }
        });
    </script>
</body>
</html>

Para mais informações sobre a biblioteca, acesse o link: https://github.com/jessepollak/card

E aí, gostou do artigo? Deixe seu comentário abaixo!

Recursão e a Pilha (Stack)

Se você não é novato em programação, e até aqueles que já fizeram algumas cadeiras/módulos de programação, provavelmente já ouviu os termos recursão e pilha.

Recursão é um método de programação onde o código executa uma função que chama a si mesma um número X de vezes para resolver um problema que apresenta um padrão repetitivo. Ela tem uma funcionalidade muito similar aos loops, mas sem explicitamente mostrar que está fazendo o mesmo trabalho repetidas vezes.

Quais as vantagens de usar recursão?

Essa é uma duvida bem comum, devo iterar? ou usar a recursão? Nos seguintes casos, seria melhor usar a recursão:

  • Reduzir o código e deixar torna-lo mais simples de ler: Para quem não está acostumado isso parece estranho, mas em grande maioria dos casos é possível escrever a mesma lógica com um número menor de linhas, tornando-o mais fácil de entender e debugar.
  • Quando você está trabalhando com uma linguagem funcional: Linguagens funcionais lidam com recursão muito melhor que imperativas. Já as linguagens imperativas lidam com iteração melhor, então leve isso em consideração quando estiver desenvolvendo seu programa ou script
  • A recursão é melhor na travessia de árvores. Este é um pouco mais avançado. Uma versão extremamente simplificada do que isso significa é a seguinte: Uma árvore é uma coleção de objetos que estão ligados um ao outro (imagine folhas em uma árvore conectada por ramos que por sua vez estão conectados a outros ramos até as raízes). Uma das maneiras mais eficientes de percorrer essas árvores ao procurar por uma folha (ou nó) específica é seguir, de maneira recursiva, uma única ramificação até o final dessa ramificação até encontrar o valor que você está procurando.

Exemplos de Recursão

Digamos que queremos criar algo simples, como uma função que faz que calcula a potencia N de um valor X (exemplo 2^3 = 8, X^N = 8).

let valor = potencia(2, 2);
//Exibe o valor 4
console.log(valor);

valor = potencia (2, 3);
//Exibe o valor 8
console.log(valor);

valor = potencia (2, 4);
//Exibe o valor 16
console.log(valor);

Importante: Este é apenas um exemplo, utilizem o objeto Math do JavaScript para esse tipo de calculo.

Poderíamos faze-lo com o Loop For

function potencia(x, n) {
  let result = 1;

  // Multiplica o resultado X N vezes para obter a resposta
  for (let i = 0; i < n; i++) {
    result *= x;
  }

  return result;
}

Console.log(potencia(2, 3) ); // 8

Agora utilizando a recursão

function potencia(x, n) {
  if (n == 1) {
    // Quando n finalmente é 1, não executa mais a recursão para finalizar o calculo
    return x;
  } else {
    //obtém a resposta do próximo pedaço do calculo chamando a função novamente
    let recursao = potencia(x, n - 1)

    return x * recursao;
  }
}

console.log(potencia(2, 3) ); // 8

Então, o que está acontecendo exatamente?

No caso da recursão deste algoritmo, quebramos a lógica em pequenos passos que fazem a multiplicação de X pelo resultado anterior até chegar em um ponto onde não é feita mais a chamada recursiva. Quando isso ocorre, as funções começam a ser retornadas e resolvidas.

No caso do exemplo acima, se fizéssemos 2^3, a ultima recursão ser no n==1 que retornaria 2 para a função anterior. Ela multiplicaria 2 * 2, resultando em quatro e retornaria para a primeira chamada que resultaria em 8 e terminaria a função.

A recursão normalmente possui menos linhas de código

A recursão normalmente é menor que a iteração. Abaixo está o mesmo exemplo que fizemos acima, mas usando o mínimo de comandos, retornos e de linhas possíveis.

function pow(x, n) {
  return (n == 1) ? x : (x * pow(x, n - 1));
}

Pilha

Uma pilha é uma região na memória, que opera no modo First-In-Last-Out, exatamente como a pilha que você deve ter estudado em estrutura de dados. Para cada nova ação que precisa ser executada, esta é “empilhada” e terá que ser processada antes da ação anterior voltar a ser trabalhada.

Note que as pilhas não tem tamanho infinito e quando você cria uma função recursiva muito grande ou mau feita, causará o famoso erro que chamamos de stack-overflow

Para ter uma ideia, execute o seguinte código

let i=0;
function estourarPilha() {
    console.log(i++);
    estourarPilha();
}
estourarPilha();

Para cada navegador os valores serão diferentes, mas eventualmente eles irão parar de funcionar pois você conseguiu quebra-los. Mas fique tranquilo, basta reinicia-lo que tudo voltará ao normal.

Conclusão

Esta foi uma introdução bem básica sobre recursão e a pilha no JavaScript, espero que você tenha aprendido com o exemplo e caso tenha alguma duvida ou sugestão por favor deixe seu comentário abaixo.

Como usar o setTimeOut

setTimeout()

Assim como a função setInterval(), o setTimeout() é uma função temporizadora que é utilizada para chamar funções de retorno após um tempo estipulado. A diferença entre essas duas funções temporizadora é que o setTimeout() chama a função apenas uma vez, e o setInterval() chama a função indefinidamente no intervalo de tempo passado, parando somente quando se utiliza a função clearInterval().

Sintaxe:

// sintaxe da função setTimeout, que define um temporizador
// que disparará uma ação definida em tempo estipulado
setTimeout(função, milissegundos, param1, param2, …);
Onde:

função: é a função que será executada no intervalo de tempo predefinido;

milissegundos: é o intervalo de tempo estipulado para a chamada da função;

param1, param2: são os parâmetros utilizados.

HTML no exemplo:

<!DOCTYPE html>
<html lang="pt-br">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <title>Exercicio setTimeOut</title>
</head>
<body>
    <section id="textoCompleta">
        <!-- O cabeçalho -->
        <h1>O texto irá preencher-se sozinho!</h1>
        <p id="type"></p>
    </section>
    <script src="main.js"></script>
</body>
</html>
E no JavaScript:
// Cria-se uma função, que possui o texto a ser mostrado
(function () {
    const text = "Este texto irá se preencher de forma automática. Estou usando o setTimeOut para definir o tempo em que as palavras serão escritas!"
    const textArea = document.getElementById("type");
    textArea.innerHTML = "";
    const textLength = text.length;

    // Nesta parte, cria-se uma variável contador e uma função
    // que irá definir o intervalo de tempo em que cada letra 
    // será mostrada de forma automática na tela.
    let contador = 0;
    function mostrarTexto() {
        if (contador <= textLength) {
            const letra = text.charAt(contador);
            textArea.textContent += letra;
            // Função setTimeOut define o tempo em milissegundos que cada letra
            // levará para ser exibida na tela.
            setTimeout(function () {
                mostrarTexto();
            }, 100);
            contador++;
        } else {
            return false;
        }
    }
    mostrarTexto();
})();

Como funciona o exemplo?

Este exemplo cria uma função que exibe letra após letra do texto inserido, de forma automática, no intervalo de tempo definido. Na função abaixo determinamos qual o texto que será inserido.

const text = "Texto que será exibido na tela!"
    // O texto precisa ser inserido em uma tag html, e essa tag deve possuir um id
    // pois este id será utilizado para identificar em qual parágrafo o texto será inserido
    const textArea = document.getElementById("type");
    textArea.innerHTML = "";
    const textLength = text.length;

Função setTimeout():

A função setTimeout irá definir o tempo em que cada letra do texto irá ser exibida na tela do usuário. Em conjunto a isto, podemos utilizar o método charAt(), que irá retornar os caracteres presentes no texto! O código textArea.textContent += letra irá retornar uma letra por vez, de maneira sequencial, da esquerda para a direita.

let contador = 0;
    function mostrarTexto() {
        if (contador <= textLength) {
            // Este código captura os caracteres do texto
            const letra = text.charAt(contador);
            // e os mostram de forma sequencial, da esquerda para a direita
            // tornando possível que o texto apareça de forma sequencial, letra por letra
            textArea.textContent += letra;
            // Função setTimeOut define o tempo em milissegundos que cada letra
            // levará para ser exibida na tela.
            setTimeout(function () {
                mostrarTexto();
            }, 100);
            contador++;
        } else {
            return false;
        }
    }

Gostou deste artigo? Deixe o seu comentário abaixo: