Aprender não precisar ser chato! Com esse artigo você vai saber como aprender JavaScript de uma maneira divertida e ainda gamificada!
Vem resolver todas as Quests! 😉
Primeiro, abra o terminal em seu sistema operacional (Windowers podem usar GIT Bash) e veja uma tela preta.
O cursor piscando na linha de comando mostra que você está no jogo.
Você pode transitar entre classes à vontade, mas a sua experiência em cada vai variar bastante.
A classe JavaScripter está em evidência hoje em dia e este guia será com base nela!
Como aprender JavaScript: Primeiros passos
Há diferentes forma de usar suas habilidades em como aprender JavaScript.
Nós utilizaremos uma que concede alguns equipamentos básicos, bastando castar npm init dentro de uma pasta.
Para habilitar o save mode, use git init uma vez e git commit -am “save” para salvar.
É interessante que em vez de save
você use uma mensagem breve e semântica do seu progresso.
Com o save mode ativado, os seus segredos podem ficar expostos a inimigos e para protegê-los, usa-se dotenv.
Crie um arquivo .env
com valor="chave"
e adicione ele em um arquivo .gitignore
.
Então acesse-os com process.get.INFO
.
Evoluções e Combos de JavaScript
Sua habilidade básica será node script.js e logo poderá ser melhorada para nodemon script.js, permitindo um fluxo melhor nas suas magias.
Uma grande evolução será utilizar nodemon –exec babel-node script.js para permitir a utilização de magias atualizadas e acompanhar o meta atual das habilidades.
npm install nodemon --save-dev npm install @babel/core @babel/node @babel/preset-env --save-dev // Crie .babelrc e coloque: { "presets": [ "@babel/preset-env" ] } node script.js nodemon script.js nodemon --exec babel-node script.js // Adicione ao package.json: "scripts": { "dev": "nodemon --exec babel-node index.js" }, npm run dev
O editor de texto é quem vai manipular o script.js e permitir diferentes resultados de acordo com o que você quer fazer.
Recomendo o VSCode com imbuí navegação de arquivos, editor de texto e terminal tudo junto, além de diversas outras vantagens.
statusReport
Quests e outros objetivos irão necessitar de diferentes recursos, como por exemplo express/koa para criar rotas e abrir portas dentro do seu domínio e react/vue para gerar interfaces e entidades visuais.
Nesta campanha, vamos criar uma aplicação em Node que verifica o status de um personagem de Habitica e posta um tweet com um resumo da situação.
Esse processo deverá acontecer toda vez que um endpoint for acessado.
Daqui pra frente assume-se que você já esteja preparado com as evoluções citadas acima.
Você também pode acompanhar o progresso das quests pelo histórico de commits dessa campanha.
Quest #1: Obter as informações do Habitica
Nós invocaremos uma magia utilitária com npm install axios
que acessará o domínio de Habitica e nos retornará as informações sobre um dado personagem.
A identificação do personagem está guardada na variável de ambiente em .env
acessada com process.env.HABITICA_USERID
.
import 'dotenv/config' import axios from 'axios' const getStats = async (userid) => { try { const response = await axios.get(`https://habitica.com/api/v3/members/${userid}`) return response.data.data.stats } catch (error) { console.log(error) } } const reportStatus = async () => { try { const stats = await getStats(process.env.HABITICA_USERID) console.log(stats) } catch (error) { console.log(error) } } reportStatus()
Percebemos a necessidade de utilizar Async/Await com Try/Catch em requisições assíncronas.
Quest #2: Gerar mensagem com base nos stats
Aqui basta um pouco de manipulação javaScripter.
Uma forma simples de exemplificar a ideia é a seguinte:
// ... const selectMessage = ({ hp = 0, maxHealth = 0, exp = 0, toNextLevel = 0 }) => { const status = `[HP: ${hp}/${maxHealth}] [EXP: ${exp.toFixed()}/${toNextLevel}]` if (hp <= maxHealth * 0.3) { return `I'm almost dying, help! ${status}` } //Também poderia ser: //if (hp <= maxHealth * 0.3) return `I'm almost dying, help! ${status}` if (exp >= toNextLevel * 0.7) { return `I'm almost leveling up! ${status}` } return `Things are fine for now. ${status}` } const reportStatus = async () => { try { const stats = await getStats(process.env.HABITICA_USERID) const message = selectMessage(stats) console.log(message) } catch (error) { console.log(error) } } reportStatus()
Neste o momento podemos identificar algumas peculiaridades como Template Literals nas strings e Object Destructuring nos parâmetros de selectMessage()
.
Quest #3: Postar no twitter
Aqui começa a dificuldade passa a aumentar e nesta solução será necessário fazer um registro no domínio dos magos do Twitter para obter tokens secretos.
Esses tokens serão utilizadas junto com o método OAuth para enviar mensagens ao domínio.
// ... import OAuth from 'oauth' // ... const reportTwitter = async (message) => { const oauth = new OAuth.OAuth( 'https://api.twitter.com/oauth/request_token', 'https://api.twitter.com/oauth/access_token', process.env.TWITTER_CONSUMER_APIKEY, process.env.TWITTER_CONSUMER_APISECRETKEY, '1.0A', null, 'HMAC-SHA1' ); return oauth.post( 'https://api.twitter.com/1.1/statuses/update.json', process.env.TWITTER_ACCESS_TOKEN, process.env.TWITTER_ACCESS_SECRETTOKEN, { status: message }, 'application/x-www-form-urlencoded', function callback(error, data, res) { if (error) { throw new Error(error.data) }; const jsonData = JSON.parse(data) const { user: { screen_name }, text } = jsonData console.log(`Tweet created! @${screen_name}: ${text}`) return true }); } const reportStatus = async () => { try { const stats = await getStats(process.env.HABITICA_USERID) const message = selectMessage(stats) return reportTwitter(message) } catch (error) { console.log(error) } } reportStatus()
Mais segredos são armazendos no .env
, JSON.parse dá as caras e Object Destructuring é aplicado na veia do jsonData.
Quest #4: Endpoint de acionamento
Nossa missão está quase concluída e aqui há algumas coisas interessantes acontecendo.
Estamos usando Koa para preparar o endpoint da api que acionará e retornará o resultado do report.
//.. import Koa from 'koa'; //... const reportTwitter = async (message) => { //... console.log(`Posting tweet with message: ${message}`) return new Promise((resolve, reject) => oauth.post( 'https://api.twitter.com/1.1/statuses/update.json', process.env.TWITTER_ACCESS_TOKEN, process.env.TWITTER_ACCESS_SECRETTOKEN, { status: message }, 'application/x-www-form-urlencoded', function callback(error, data, res) { if (error) { const errorMessage = error.data console.log('Error: could not post tweet ', errorMessage) return resolve(errorMessage) }; const jsonData = JSON.parse(data) const { user: { screen_name }, text } = jsonData const successMessage = `Tweet created! @${screen_name}: ${text}` console.log(successMessage) return resolve(successMessage) })); } const reportStatus = async () => { try { const stats = await getStats(process.env.HABITICA_USERID) const message = selectMessage(stats) const response = await reportTwitter(message) return response } catch (error) { console.log(error) } } const app = new Koa(); app.use(async (ctx) => { const message = await reportStatus() ctx.response.body = message }); app.listen(3000);
E se olharmos mais de perto, veremos que a função reportTwitter()
agora retorna uma Promise.
Isso teve que ser feito, pois oauth.post()
não retorna uma Promise por padrão e precisamos que seja assim para exibir o retorno no ctx.response.body
.
Note que a função não é rejeitada() no erro, mas sim resolvida() para que exiba a mensagem de erro na tela (ctx).
Quest #5: Deploy
Como passo final dessa missão de como aprender JavaScript, subiremos a nossa criação às nuvens.
Utilizaremos o utilitário Now instalando ele globalmente com npm install -g now
, criando uma conta digitando now
e adicionando nosso segredos de forma segura em nossa conta com
now secrets add habitica-userid <userid>
now secrets add twitter-consumer-apikey <key>
now secrets add twitter-consumer-apisecretkey <key>
now secrets add twitter-access-token <token>
now secrets add twitter-access-secrettoken <token>
E com mais algumas configurações no now.json…
{ "version": 2, "builds": [ { "src": "index.js", "use": "@now/node-server" } ], "env": { "HABITICA_USERID": "@habitica-userid", "TWITTER_CONSUMER_APIKEY": "@twitter-consumer-apikey", "TWITTER_CONSUMER_APISECRETKEY": "@twitter-consumer-apisecretkey", "TWITTER_ACCESS_TOKEN": "@twitter-access-token", "TWITTER_ACCESS_SECRETTOKEN": "@twitter-access-secrettoken" } }
Invoque now
na linha de comando e missão cumprida.
Cronomagia é difícil para saber como aprender JavaScript?
A ideia inicial era que esse report acontecesse todos os dias em um horário específico e isso foi facilmente alcançado usando um simples node-cron:
import cron from 'node-cron' cron.schedule('30 19 * * *', () => reportStatus())
Mas como no Heroku e no Now aplicações ficam sleeping, as coisas ficaram bem mais complicadas.
Qual será o próximo desafio?
Uma boa continuação dessa campanha envolveria fazer testes, refatorar, organizar em arquivos, transformar em um container Docker e subir ele na AWS.
Se você quiser jogar esse jogo na vida real, vem dar uma olhada na nossa páginas de vagas para programadores em JavaScript!
O que achou? Gostaria de mais tutoriais assim? Deixe uma mensagem nos comentários o/