Apostila de NodeJS 100% Gratuita - Reativa Tecnologia
Apostila de NodeJS 100% Gratuita - Reativa Tecnologia
Apostila de NodeJS 100% Gratuita - Reativa Tecnologia
Introdução ao Node.js
Node.js é um ambiente de execução JavaScript open source e multiplataforma.
É uma ferramenta popular para quase todo tipo de projeto!
Node.js roda na engine (motor) V8, o coração do Google Chrome, fora do
navegador. Isso permite que o Node.js seja muito performático.
Uma aplicação Node.js roda em um único processo, sem criar uma nova thread
para cada requisição. O Node.js provê uma série de primitivas assíncronas para
I/O (input/output) em sua biblioteca nativa que previnem códigos JavaScript
bloqueantes, e geralmente, bibliotecas em Node.js são escritas usando como
padrão paradigmas não-bloqueantes, fazendo com que o comportamento de
bloqueio seja uma excessão a regra.
Quando o Node.js executa operações de I/O, como ler dados da rede, acessar um
banco de dados ou o sistema de arquivos, em vez de bloquear a thread em
execução e gastar ciclos de CPU esperando, o Node.js vai continuar com as
operações quando a resposta retornar.
Isso permite com que o Node.js lide com centenas de conexões paralelas em um
único servidor, removendo o fardo de gerenciar concorrências em threads, que
podem ser fontes signi cativas de bugs.
Hello World!
Loading Project
Glitch Tip!
Turn your code into a perfectly formatted masterpiece with the
"Format This File" button
Para executar esse trecho, salve-o como server.js e rode com node
server.js no seu terminal.
Primeiramente esse código importa o módulo http
http.
res.statusCode = 200
nós de nimos a propriedade statusCode como 200, para indicar uma resposta
bem sucedida.
res.setHeader('Content-Type', 'text/plain')
Express: Provê os meios de se criar servidores web de uma forma muito simples
porém poderosa. Têm uma pegada minimalista, não opinada, focada nas
funções essenciais de um servidor, que são a chave do sucesso.
koa: É mantido pelo time por trás do Express, pretende ser ainda menor e
simples, construido sob muitos anos de conhecimento. O novo projeto nasceu
da necessidade de criar mudanças incompatíveis sem romper com a
comunidade existente.
Loopback.io: Faz com que seja fácil construir aplicações modernas que
requerem integrações complexas.
Meteor: Um framework full-stack incrivelmente poderoso, permite que você
crie aplições Javascript com uma abordagem isomór ca, compartilhando
código entre cliente e servidor. É uma ferramenta generalista que tenta
fornecer tudo, que agora integra com bibliotecas frontend como React, Vue, e
Angular. Também pode ser utilizado para criar aplicativos mobile.
Na tecnologia, 11 anos não é um tempo muito longo, mas o Node.js parece ter
existido sempre.
Um pouco de história
JavaScript é uma linguagem de programação que foi criada no Netscape como
uma ferramente de scripts para manipulação de páginas web dentro do browser
Netscape Navigator.
Um fator chave que levou o Node.js ao topo foi o timing. Apenas alguns poucos
anos antes, Javascript começou a ser mais considerado como uma linguagem
séria, graças às aplicações “Web 2.0” (como Flickr, Gmail, etc.) que mostraram
ao mundo como poderia ser uma experiência moderna na web.
Aconteceu de o Node.js ser criado no lugar certo e na hora certa, mas sorte não
é a única razão do porquê ser tão popular hoje. Ele introduz várias abordagens e
estratégias inovadoras para o desenvolvimento sever-side com JavaScript que
já ajudaram diversos desenvolvedores.
2009
Nasce o Node.js
2010
Nasce o Express
Nasce o Socket.io
2011
npm alcança a versão 1.0
Nasce o hapi
2012
Adoção continua muito rápida
2013
Primeira grande plataforma de blogs usando Node.js: Ghost
Nasce o Koa
2014
O Grande Fork: io.js é o maior fork do Node.js, com o objetivo de introduzir
suporte ao ES6 e crescer rapidamente.
2015
Nasce a Node.js Foundation
2016
O incidente de leftpad
Nasce o Yarn
Node.js 6
2017
npm aumenta o foco em segurança
Node.js 8
HTTP/2
V8 introduz o Node.js em sua suite de testes, fazendo do Node.js o cialmente
um alvo da engine, em adição ao Chrome
2018
Node.js 10
Node.js 11
2019
Node.js 12
Node.js 13
2020
Node.js 14
Node.js 15
nvm é um maneira muito popular de rodar Node.js. Ele permite que você troque
facilmente entre versões, e instale novas versões para testar e troque de volta
caso algo pare de funcionar, por exemplo.
Também é muito útil para testar seu código com versões antigas do Node.js
Enquanto aprende a programar, você também pode car confuso sobre onde o
JavaScript termina, e onde o Node.js começa, e vice versa.
Eu recomendo que você tenha um bom domínio dos principais conceitos do
JavaScript antes de mergulhar no Node.js:
Estrutura Léxica
Expressões
Tipos
Variáveis
Funções
this
Arrow Functions
Loops
Escopos
Arrays
Template Literals
Semicolons (;)
Strict Mode
Com esses conceitos em mente, você está no caminho certo para se tornar um
desenvolvedor pro ciente em JavaScript, tanto Browser como também Node.js.
Timers
Promises
Async e Await
Closures
Event Loop
Você tem uma grande oportunidade porque nós sabemos quão difícil é para
aprender, completa e profundamente, uma nova linguagem de programação, e
por usar a mesma linguagem para fazer todo o trabalho na web - tanto no
servidor quanto no cliente, você está em uma posição única de vantagem.
E no browser, nós não temos as APIs legais que o Node.js provê com seus
módulos, como a funcionalidade de acesso ao lesystem.
Outra grande diferença é que no Node.js você controla seu ambiente. A não ser
que você esteja criando uma aplicação open source que qualquer um pode
hospedar em qualquer lugar, você sabe em qual versão do Node.js a aplicação
vai rodar. Comparado ao ambiente do browser, onde você não tem o luxo de
escolher qual browser seu visitante vai utilizar, isso é muito conveniente.
Isso signi ca que você pode escrever códigos com os modernos ES6-7-8-9, se
atentando ao suporte da sua versão do Node.js.
Visto que o JavaScript se move muito rápido, mas os browsers podem ser um
pouco lentos para atualizarem, as vezes na web, você está preso em versões
velhas do JavaScript / ECMAScript.
Na prática, isso signifca que por enquanto você utiliza require() no Node.js e
import no browser.
O motor V8 do JAvascript
V8 é o nome da engine JavaScript que roda no Google Chrome. É a coisa que
pega nosso JavaScript e o executa enquanto navegamos com o Chrome.
Outras engines JS
Outros browsers têm suas pŕopias engines:
Na web, há uma corrida por performance que vem sendo travada por anos, e
nós (como usuários e desenvolvedores) nos bene ciamos muito por essa
competição, porque nós possuímos máquinas mais rápidas e otimizadas ano a
ano.
Compilação
JavaScript é geralmente considerado como uma linguagem interpretada, mas
engines modernas de JavaScript não o interpretam apenas, elas o compilam.
Nossas aplicações agora podem rodar por horas dentro do browser, em vez de
uma simples validação de regras de formulários ou scripts banais.
Nesse novo mundo, compilar JavaScript faz total sentido porque, embora possa
demorar um pouco mais para termos o código JavaScript pronto, uma vez
concluída a compilação temos muito mais desempenho do que código
puramente interpretado.
node app.js
Vamos começar com a maneira mais drástica, e note porque é melhor você não
utilizá-la:
Isso signi ca que qualquer callback pendente, qualquer request de rede sendo
enviada, qualquer acesso ao lesystem, ou processos de escrita no stdout ou
stderr - tudo será nalizado de imediato desgraciadamente.
Se isso está bem para você, basta passar um inteiro que sinalize o código de
saída para o sistema operacional:
process.exit(1)
process.exitCode = 1
Muitas vezes nós iniciamos servidores Node.js, como esse servidor HTTP:
Nesse caso, você precisa enviar ao comando um sinal de SIGTEM, e lidar com o
processo desse sinal:
process.on('SIGTERM', () => {
server.close(() => {
console.log('Process terminated')
})
})
SIGKILL é o sinal que diz ao processo para que nalize imediatamente, e agirá
idealmente como o process.exit()
process.exit().
Você pode enviar esse sinal por dentro da aplicação, em outra função:
process.kill(process.pid, 'SIGTERM')
process.env.NODE_ENV // "development"
node script.js
node
Se você tentar isso agora no seu terminal, isto é o que vai acontecer:
❯ node
>
Para ser mais exato, o REPL está aguardando a entrada de código JavaScript.
> console.log('test')
test
undefined
>
Conforme você escreve seu código, se você pressionar o tecla tab o REPL vai
tentar completar o que foi escrito para combinar com variáveis previamente
de nidas.
O REPL vai listar todas as propriedades e métodos que você pode acessar
naquela classe:
Explore objetos globais
Você pode inspecionar os objetos globais que você tem acesso digitando
global. e pressionando tab
tab:
á
A variável especial _
Se depois de um código você digitar _ , isso fará com que seja exibido o
resultado da última operação.
.save: salva todas suas entradas na sessão REPL em um arquivo (especi que
.save
um nome pro arquivo)
O REPL sabe quando você está inserindo uma entrada com múltiplas linhas sem
a necessidade de utilizar o .editor
.editor.
e pressionar enter
enter, o REPL irá para uma nova linha que começa com 3 pontos,
indicando que você pode continuar a trabalhar naquele bloco.
... console.log(num)
... })
Se você digitar .break no m de uma linha, o modo múltiplas linhas irá parar
e o código não será executado.
node app.js
Por exemplo:
ou
Já nesse caso:
args[0] é name=joe,
name=joe e você precisa tratá-lo. A melhor maneira de fazer isso é
usando a biblioteca minimist
minimist, que ajuda a lidar com argumentos:
Desta vez você você precisa usar dois traços antes do nome do argumento:
node app.js --name=joe
const x = 'x'
const y = 'y'
console.log(x, y)
Por exemplo:
Exemplo:
console.log('%o', Number)
Limpando o console
console.clear() limpa o console (o comportamento pode mudar
dependendo do console utilizado).
Contando elementos
console.count() é um método muito conveniente.
Dado o código:
Loading Project
Glitch Tip!
Search for and add third party libraries in package.json
const x = 1
const y = 2
const z = 3
console.count(
'O valor de x é ' + x + ' e foi validado .. quantas vezes?'
)
console.count(
'O valor de x é ' + x + ' e foi validado .. quantas vezes?'
)
console.count(
'O valor de y é ' + y + ' e foi validado .. quantas vezes?'
)
O que acontece é que ele vai contar o número de vezes que uma string foi
impressa, e imprime o total:
Isso irá imprimir a pilha de execução. Isso é o que é impresso se tentarmos usá-
lo no REPL do Node.js:
Trace
at function2 (repl:1:33)
at function1 (repl:1:25)
at repl:1:1
at ContextifyScript.Script.runInThisContext (vm.js:44:33)
at REPLServer.defaultEval (repl.js:239:29)
at bound (domain.js:301:14)
at REPLServer.runBound [as eval] (domain.js:314:12)
at REPLServer.onLine (repl.js:440:10)
at emitOne (events.js:120:20)
at REPLServer.emit (events.js:210:7)
stdout e stderr
Como nós vimos o console.log é ótimo para imprimir mensagens no console.
Isso é o que chamamos de saída padrão, ou stdout
stdout.
Isso não vai aparecer no console, mas vai aparecer no log de erro.
Colorindo o saída
Você pode colorir a saída do seu texto no console utilizando escape sequences,
que basicamente são um conjunto de caracteres que indenti cam uma cor.
Exemplo:
console.log('\x1b[33m%s\x1b[0m', 'hi!')
Você pode testar isso no REPL no Node.js, onde será impresso hi! em amarelo.
Entretanto, essa é uma abordagem mais baixo nível. O jeito mais simples de
colorir saídas no console é utilizando uma biblioteca. Chalk é uma biblioteca
que além de colorir, também ajuda com outras facilidades de estilização, como
deixar textos em negrito, ítalico ou sublinhados.
Instale com npm install chalk,
chalk e então use-o assim:
Esse trecho cria uma barra de progresso com 10 passos, e a cada 100ms um
passo é completado. Quando a barra é completada nós nalizamos o contador.
Esse trecho de código pergunta o nome do usuário, e uma vez que o texto é
inserido e o usuário pressiona enter, nós enviamos uma saudação.
Se você precisa solicitar uma senha, o ideal é que os caracteres digitados sejam
trocados pelo símbolo de * .
var questions = [
{
type: 'input',
name: 'name',
message: "What's your name?"
}
]
inquirer.prompt(questions).then(answers => {
console.log(`Hi ${answers['name']}!`)
})
Inquirer.js permite com que você faça diversas coisas como perguntas de
múltipla escolha, ter radio buttons, con rmações e muito mais.
Nesse arquivo, a funcionalidade deve ser exposta antes de poder ser importada
por outros arquivos.
Quando você atribui um objeto ou uma função como uma nova propriedade do
exports, isso se torna o que está sendo exposto, e como tal, pode ser
exports
importado em outras partes da sua aplicação, ou até em outras aplicações.
const car = {
brand: 'Ford',
model: 'Fiesta'
}
module.exports = car
const car = {
brand: 'Ford',
model: 'Fiesta'
}
exports.car = car
ou diretamente
exports.car = {
brand: 'Ford',
model: 'Fiesta'
}
ou
O primeiro expõe o objeto para qual ele aponta. O último expõe as propriedades
do objeto que ele aponta.
Introdução ao npm
npm é o gerenciador de pacotes padrão do Node.js.
Downloads
npm gerencia downloads de dependências do seu projeto.
npm install
npm update
o npm vai buscar em todos os pacotes por uma versão atualizada que satisfaça
suas restrições de versionamento.
Versionamento
Em adição aos downloads, o npm também gerencia o versionamento, assim
você pode especi car qualquer versão do pacote, ou uma versão maior ou
menor do que você precisa.
Muitas vezes você vai encontrar uma biblioteca que só é compatível com a
versão atual de outra biblioteca.
Executando tarefas
O arquivo package.json possui um campo chamado “scripts”, que é usado para
especi car tarefas de linha de comando que podem ser rodadas usando
Por exemplo:
{
"scripts": {
"start-dev": "node lib/server-development",
"start": "node lib/server-production"
},
}
{
"scripts": {
"watch": "webpack --watch --progress --colors --config web
"dev": "webpack --progress --colors --config webpack.conf.
"prod": "NODE_ENV=production webpack -p --config webpack.c
},
}
Então em vez de digitar esses comandos longos, que são muito fáceis de errar
ou esquecer, você pode rodar
global
Quando isso ocorre, o npm não instalará na pasta local, em vez disso, ele
utilizará uma localização global.
Onde, exatamente?
Eu por exemplo utilizo nvm e a localização dos meus pacotes foi exibida como
/Users/joe/.nvm/versions/node/v8.9.0/lib/node_modules.
/Users/joe/.nvm/versions/node/v8.9.0/lib/node_modules
Como usar ou executar um pacote instalado
usando NPM?
Quando você instala um pacote usando npm dentro da sua pasta
node_modules, ou também globamente, como você o utiliza em seu código
node_modules
Node.js?
const _ = require('lodash')
O pacote cowsay fornece um programa de linha de comando que faz com que
uma vaca diga algo (e outros animais também 🦊).
Quando você instala o pacote utilizando npm install cowsay,
cowsay ele irá instalar
a si mesmo e algumas poucas dependências na sua pasta node_modules local:
Há uma pasta oculta chamada .bin, que contêm links simbólicos para os
binários do cowsay:
npx cowsay
Pra que ele serve? O que você deveria saber sobre ele, e o quê de legal pode ser
feito com ele?
The le structure
Aqui temos um exemplo de arquivo package.json:
{}
Está vazio! Não há campos xos obrigatórios do que pode ser colocado no
arquivo package.json
package.json, de uma aplicação. A única exigência é que respeite o
formato JSON, caso contrário programas que tentem acessar as propriedades
programaticamente não terão sucesso.
Se você está criando um pacote Node.js que precisa ser distribuido no npm as
coisas mudam radicalmente, e você necessita preencher algumas propriedades
que vão ajudar outras pessoas a utilizar seu pacote. Vamos ver mais sobre isso
em breve.
Esse é outro package.json:
{
"name": "test-project"
}
Aqui temos outro exemplo muito mais complexo, que foi extraido de uma
aplicação Vue.js:
{
"name": "test-project",
"version": "1.0.0",
"description": "A Vue.js project",
"main": "src/main.js",
"private": true,
"scripts": {
"dev": "webpack-dev-server --inline --progress --config bu
"start": "npm run dev",
"unit": "jest --config test/unit/jest.conf.js --coverage",
"test": "npm run unit",
"lint": "eslint --ext .js,.vue src test/unit",
"build": "node build/build.js"
},
"dependencies": {
"vue": "^2.5.2"
},
"devDependencies": {
"autoprefixer": "^7.1.2",
"babel-core": "^6.22.1",
"babel-eslint": "^8.2.1",
"babel-helper-vue-jsx-merge-props": "^2.0.3",
"babel-jest": "^21.0.2",
"babel-loader": "^7.1.1",
"babel-plugin-dynamic-import-node": "^1.2.0",
"babel-plugin-syntax-jsx": "^6.18.0",
"babel-plugin-transform-es2015-modules-commonjs": "^6.26.0
"babel-plugin-transform-runtime": "^6.22.0",
"babel-plugin-transform-vue-jsx": "^3.5.0",
"babel-preset-env": "^1.3.2",
"babel-preset-stage-2": "^6.22.0",
"chalk": "^2.0.1",
"copy-webpack-plugin": "^4.0.1",
"css-loader": "^0.28.0",
"eslint": "^4.15.0",
"eslint-config-airbnb-base": "^11.3.0",
"eslint-friendly-formatter": "^3.0.0",
"eslint-import-resolver-webpack": "^0.8.3",
"eslint-loader": "^1.7.1",
"eslint-plugin-import": "^2.7.0",
"eslint-plugin-vue": "^4.0.0",
"extract-text-webpack-plugin": "^3.0.0",
"file-loader": "^1.1.4",
"friendly-errors-webpack-plugin": "^1.6.1",
"html-webpack-plugin": "^2.30.1",
"jest": "^22.0.4",
"jest-serializer-vue": "^0.3.0",
"node-notifier": "^5.1.2",
"optimize-css-assets-webpack-plugin": "^3.2.0",
"ora": "^1.2.0",
"portfinder": "^1.0.13",
"postcss-import": "^11.0.0",
"postcss-loader": "^2.0.8",
"postcss-url": "^7.2.1",
"rimraf": "^2.6.0",
"semver": "^5.3.0",
"shelljs": "^0.7.6",
"uglifyjs-webpack-plugin": "^1.1.1",
"url-loader": "^0.5.8",
"vue-jest": "^1.0.2",
"vue-loader": "^13.3.0",
"vue-style-loader": "^3.0.1",
"vue-template-compiler": "^2.5.2",
"webpack": "^3.6.0",
"webpack-bundle-analyzer": "^2.9.0",
"webpack-dev-server": "^2.9.1",
"webpack-merge": "^4.1.0"
},
"engines": {
"node": ">= 6.0.0",
"npm": ">= 3.0.0"
},
"browserslist": ["> 1%", "last 2 versions", "not ie <= 8"]
}
scripts de ne alguns scripts node que você pode rodar na linha de comando
browserslist é usado para de nir quais browsers (e suas versões) você quer
dar suporte
Todas essas propriedades são usadas tanto pelo npm quando outras
ferramentas.
Separação de propriedades
Essa seção descreve as propriedades que você pode usar em detalhes. Nós nos
referimos como “pacote” mas o mesmo se aplica à aplicações locais que você
não utiliza como pacotes.
De ne o nome do pacote.
Exemplo:
"name": "test-project"
O nome deve ter menos de 214 caracteres, não pode ter espaços, apenas letras
minúsculas, hífens ( - ) ou underlines ( _ ).
Se você publicou esse pacote no GitHub, é uma boa de nir essa propriedade
com o nome do repositório no GitHub.
author
Exemplo:
{
"author": "Joe <[email protected]> (https://whatever.com)"
}
{
"author": {
"name": "Joe",
"email": "[email protected]",
"url": "https://whatever.com"
}
}
contributors
Exemplo:
{
"contributors": ["Joe <[email protected]> (https://whatever.c
}
{
"contributors": [
{
"name": "Joe",
"email": "[email protected]",
"url": "https://whatever.com"
}
]
}
bugs
Exemplo:
{
"bugs": "https://github.com/whatever/package/issues"
}
homepage
De ne a página inicial do site do pacote
Exemplo:
{
"homepage": "https://whatever.com/package"
}
version
Exemplo:
"version": "1.0.0"
Há um signi cado nesses números: uma versão que só corrige bugs é uma
versão patch, uma versão que introduz mudanças compatíveis com versões
anteriores é uma versão minor, uma versão major pode conter quebra de
comportamentos com versões antigas.
license
Exemplo:
"license": "MIT"
keywords
Esse propriedade contêm um array de palavras chave que são associadas a o quê
esse projeto faz.
Exemplo:
"keywords": [
"email",
"machine learning",
"ai"
]
Isso ajuda pessoas a encontrarem seu pacote quando estiverem navegando por
pacotes semelhantes, ou quando estiverem navegando no site
https://www.npmjs.com/.
description
Exemplo:
repository
"repository": "github:whatever/testing",
"repository": "gitlab:whatever/testing",
"repository": "bitbucket:whatever/testing",
"repository": {
"type": "git",
"url": "https://github.com/whatever/testing.git"
}
"repository": {
"type": "svn",
"url": "..."
}
main
Quando você importa esse pacote em uma aplicação, é onde a aplicação vai
procurar pelo module exports.
Exemplo:
"main": "src/main.js"
private
Exemplo:
"private": true
scripts
Exemplo:
"scripts": {
"dev": "webpack-dev-server --inline --progress --config buil
"start": "npm run dev",
"unit": "jest --config test/unit/jest.conf.js --coverage",
"test": "npm run unit",
"lint": "eslint --ext .js,.vue src test/unit",
"build": "node build/build.js"
}
Esses scripts são aplicações de linha de comando. Você pode rodá-los usando
npm run XXXX ou yarn XXXX,
XXXX sendo XXXX o nome do comando. Exemplo:
npm run dev.
dev
Você pode usar o nome que quiser para o comando, e os scripts podem fazer
qualquer coisa.
dependencies
Exemplo:
"dependencies": {
"vue": "^2.5.2"
}
devDependencies
Exemplo:
"devDependencies": {
"autoprefixer": "^7.1.2",
"babel-core": "^6.22.1"
}
engines
Exemplo:
"engines": {
"node": ">= 6.0.0",
"npm": ">= 3.0.0",
"yarn": "^0.13.0"
}
browserslist
É usado para de nir quais browsers (e suas versões) você deseja dar suporte. É
refenciado pelo Babel, Autopre xer, e outras ferramentas, apenas para
adicionar poly lls e fallbacks necessárias para o browser em questão.
Exemplo:
"browserslist": [
"> 1%",
"last 2 versions",
"not ie <= 8"
]
Essa con guração implica que você quer dar suporte paras as 2 últimas versões
major de todos os browsers com pelo menos 1% de uso (das estatísticas do
CanIUse.com), exceto IE8 ou anterior.
Você pode combinar a maioria das versões em intervalos, como esse: 1.0.0 ||
<1.2.0 para usar ou 1.0.0 ou uma versão maior ou igual que 1.1.0,
>=1.1.0 <1.2.0,
mas menor que 1.2.0.
O arquivo package-lock.json
Na versão 5, o npm introduziu o arquivo package-lock.json
package-lock.json.
O objeto do arquivo é manter rastreada a versão exata de cada pacote que está
instalado, assim o produto é 100% reproduzível mesmo que pacotes sejam
atualizados pelos seus mantenedores.
Pode ser com você, ou com outra pessoa do outro lado do mundo tentando
inicializar o projeto rodando npm install.
install
Então seu projeto original e o novo projeto recém inicializado são na verdade
diferentes. Mesmo que uma versão patch ou minor não introduza mudanças
que quebrem códigos antigos, nós todos sabemos que bugs podem (e vão)
surgir.
Um exemplo
Essa é uma estrutura de exemplo de um arquivo package-lock.json que é
obtida quando rodamos npm install cowsay em uma pasta vazia:
{
"requires": true,
"lockfileVersion": 1,
"dependencies": {
"ansi-regex": {
"version": "3.0.0",
"resolved": "https://registry.npmjs.org/ansi-regex/-/ans
0.0.tgz",
"integrity": "sha1-7QMXwyIGT3lGbAKWa922Bas32Zg="
},
"cowsay": {
"version": "1.3.1",
"resolved": "https://registry.npmjs.org/cowsay/-/cowsay-
,
"integrity": "sha512-3PVFe6FePVtPj1HTeLin9v8WyLl+VmM1l1H
Ajufp+0F9eLjzRnOHzVAYeIYFF5po5NjRrgefnRMQ==",
"requires": {
"get-stdin": "^5.0.1",
"optimist": "~0.6.1",
"string-width": "~2.1.1",
"strip-eof": "^1.0.0"
}
},
"get-stdin": {
"version": "5.0.1",
"resolved": "https://registry.npmjs.org/get-stdin/-/get-
1.tgz",
"integrity": "sha1-Ei4WFZHiH/TFJTAwVpPyDmOTo5g="
},
"is-fullwidth-code-point": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/is-fullwidth-cod
is-fullwidth-code-point-2.0.0.tgz",
"integrity": "sha1-o7MKXE8ZkYMWeqq5O+764937ZU8="
},
"minimist": {
"version": "0.0.10",
"resolved": "https://registry.npmjs.org/minimist/-/minim
.tgz",
"integrity": "sha1-3j+YVD2/lggr5IrRoMfNqDYwHc8="
},
"optimist": {
"version": "0.6.1",
"resolved": "https://registry.npmjs.org/optimist/-/optim
"integrity": "sha1-2j6nRob6IaGaERwybpDrFaAZZoY=",
"requires": {
"minimist": "~0.0.1",
"wordwrap": "~0.0.2"
}
},
"string-width": {
"version": "2.1.1",
"resolved": "https://registry.npmjs.org/string-width/-/s
"integrity": "sha512-nOqH59deCq9SRHlxq1Aw85Jnt4w6KvLKqWV
"requires": {
"is-fullwidth-code-point": "^2.0.0",
"strip-ansi": "^4.0.0"
}
},
"strip-ansi": {
"version": "4.0.0",
"resolved": "https://registry.npmjs.org/strip-ansi/-/str
"integrity": "sha1-qEeQIusaw2iocTibY1JixQXuNo8=",
"requires": {
"ansi-regex": "^3.0.0"
}
},
"strip-eof": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/strip-eof/-/stri
"integrity": "sha1-u0P/VZim6wXYm1n80SnJgzE2Br8="
},
"wordwrap": {
"version": "0.0.3",
"resolved": "https://registry.npmjs.org/wordwrap/-/wordw
"integrity": "sha1-o9XabNXAvAAI03I0u68b7WMFkQc="
}
}
}
get-stdin
optimist
string-width
strip-eof
Por sua vez, esses pacotes dependem de outros pacotes, como podemos ver nos
requires de alguns deles:
ansi-regex
is-fullwidth-code-point
minimist
wordwrap
strip-eof
npm list
Por exemplo:
❯ npm list
/Users/joe/dev/node/cowsay
└─┬ [email protected]
├── [email protected]
├─┬ [email protected]
│ ├── [email protected]
│ └── [email protected]
├─┬ [email protected]
│ ├── [email protected]
│ └─┬ [email protected]
│ └── [email protected]
└── [email protected]
Para obter obter apenas os pacotes top-level (basicamente aqueles que você
pediu para o npm instalar e estão listados no package.json
package.json), execute npm
list --depth=0:
--depth=0
1.3.1
Exemplo:
[ '1.0.0',
'1.0.1',
'1.0.2',
'1.0.3',
'1.1.0',
'1.1.1',
'1.1.2',
'1.1.3',
'1.1.4',
'1.1.5',
'1.1.6',
'1.1.7',
'1.1.8',
'1.1.9',
'1.2.0',
'1.2.1',
'1.3.0',
'1.3.1' ]
{
"dependencies": {
"cowsay": "^1.3.1"
}
}
{
"requires": true,
"lockfileVersion": 1,
"dependencies": {
"cowsay": {
"version": "1.3.1",
"resolved": "https://registry.npmjs.org/cowsay/-/cowsay-
"integrity": "sha512-3PVFe6FePVtPj1HTeLin9v8WyLl+VmM1l1H
"requires": {
"get-stdin": "^5.0.1",
"optimist": "~0.6.1",
"string-width": "~2.1.1",
"strip-eof": "^1.0.0"
}
}
}
}
Agora esses 2 arquivos nos dizem que instalamos a versão 1.3.1 do cowsay, e
nossa regra para atualizações é ^1.3.1
^1.3.1, o que o npm pode atualizar para
versões patch e minor: 1.3.2,
1.3.2 1.4.0 e assim por diante.
Algumas dessas atualizações são para versões major. Executando npm update
elas não serão atualizadas. Versões major nunca são atualizadas desse jeito
porque elas (por de nição) introduzem mudanças sujeitas a quebras em
versões antigas, e o npm quer nos poupar desse problema.
Para atualizar para uma versão major desses pacotes, instale o pacote npm-
check-updates globalmente:
e então rode:
ncu -u
npm update
npm install
Quando você cria uma nova versão, você não aumenta um número como bem
entender, existem algumas regras:
você aumenta a versão major quando você cria mudanças de API incompatíveis
você aumenta a versão patch quando você arruma bugs sem quebrar versões
anteriores
>
>=
<
<=
||
Você pode combinar algumas dessas notações, por exemplo, utilize 1.0.0 ||
>=1.1.0 <1.2.0 para usar 1.0.0 ou uma versão maior ou igual a 1.1.0, porém
menor que 1.2.0.
Usando a ag -S
-S, ou --save
--save, essa operação também irá remover a referência
no arquivo package.json
package.json.
por exemplo:
e você pode rodar esse comando em qualquer lugar do seu sistema pois a pasta
que você está não importa. and you can run this command from anywhere you
want on your system because the folder where you currently are does not
matter.
pacotes locais são instalados no diretório em que você executa npm install
<package-name>, e eles são inseridos na pasta node_modules desse diretório.
<package-name>
require('package-name')
Isso garante que você possa ter dúzias de aplicações no seu computador, todas
rodando com uma versão diferente de cada pacote se necessário.
Atualizar um pacote global fará com que todos seus projetos usem a nova
versão, e como você pode imaginar isso pode causar pesadelos em termos de
manutenção, pois alguns pacotes podem quebrar.
Todos projetos tem sua própria versão local de um pacote, mesmo que isso
possa parecer um desperdício de recursos, é algo pequeno comparado as
possíveis consequências.
Alguns otimos exemplos de pacotes globais populares que você pode conhecer:
npm
create-react-app
vue-cli
grunt-cli
mocha
react-native-cli
gatsby-cli
forever
nodemon
Quando você vai para produção, se digitar npm install e a pasta conter um
arquivo package.json
package.json, elas são instaladas, pois o npm assume que é um
deploy de desenvolvimento.
Conhecendo o NPX
npx é um comando poderoso que está disponível no npm a partir da versão 5.2,
lançada em Julho de 2017.
Se você não quer instalar o npm, você pode instalar o npx como um
pacote standalone
O npx permite rodar seu código feito com Node.js e publicado nos registros do
npm.
Isso é bem chato poque você não pode instalar versões diferentes do mesmo
comando.
O npx permite que você rode o comando sem tê-lo instalado localmente:
rodar a CLI do vue para criar novas aplicações: npx @vue/cli create my-
vue-app
npx https://gist.github.com/zkat/4bc19503fe9e9309e2bfaa2c58074
Mas é claro que você precisa ter cuidado ao rodar códigos que estão fora do seu
controle, com grandes poderes vem grandes responsabilidades.
Introdução
O Evnet Loop é um dos aspectos do Node.js mais importantes de se entender.
Por que ele é tão importante? Porque ele explica como o Node.js pode ser
assíncrono e ter I/O não bloqueante, e também explica o diferencial do Node.js,
o quê fez dele bem-sucedido.
O código JavaScript Node.js roda em uma única thread. Há apenas uma coisa
acontecendo por vez.
Essa é uma limitação que na verdade é bem útil, pois ela simpli ca muito como
você programa sem se preocupar com problemas de concorrência.
Você só precisa prestar atenção em como escrever seu código e evitar qualquer
coisa que possa bloquear a thread, como chamadas de rede síncronas ou loops
in nitos.
No geral, na maioria dos browsers existe um event loop para cada aba aberta,
para tratar cada processo de forma isolada e evitar que uma página web com
loops in nitos ou processamento pesado bloqueie o browser por completo.
Você precisa se preocupar principalmente com que seu código rode um único
event loop, e escrever o código com isso em mente a m de evitar bloquear a
thread.
A call stack
A call stack (pilha de chamadas) é uma la do tipo LIFO (Last In, First Out, que
em português signi ca último a entrar, primeiro a sair).
O event loop checa continuamente a call stack para ver se há qualquer função
que precise rodar.
Enquanto faz isso, ele adiciona na call stack qualquer chamada de função que
encontrar e executa cada uma em ordem.
Sabe quando ocorre um erro e no debugger ou no console do browser aparece
uma sequência hierárquica de nomes de funções? Basicamente o browser
procura os nomes das funções na call stack para te informar qual função
originou a chamada corrente:
Glitch Tip!
Securely store app secrets and config in .env
This site is protected by reCAPTCHA and the Google Privacy Policy and Terms
of Service apply.
Vamos ver como adiar uma função até que a stack esteja vazia.
Loading Project
Glitch Tip!
Turn your code into a perfectly formatted masterpiece with the "Format
This File" button
This site is protected by reCAPTCHA and the Google Privacy Policy and Terms
of Service apply.
foo
baz
bar
Quando esse código roda, primeiro foo() é chamada. Dentro de foo() nós
chamamos setTimeout, passando bar como um argumento, e nós instruimos
a rodá-la imediatamente, o mais rápido possível, passando 0 como o tempo de
contagem. E então nós chamamos baz().
A Message Queue
Quando setTimeout() é chamado, o Browser ou o Node.js começa a contagem.
Uma vez que ela encerre, nesse caso imediatamente pois de nimos 0 como
parâmetro, a função callback é colocada na Message Queue ( la de
mensagens).
A Message Queue também é onde estão eventos iniciados pelo usuário, como
clicks ou pressionamento de teclas, ou respostas de requisições en leiradas.
antes do seu código ter a oportunidade de reagir à elas. Ou também eventos do
DOM, como onLoad
onLoad.
O loop dá prioridade à call stack, primeiro ele processa tudo que encontrar na
call stack, e só depois que não há nada lá, ele começa a pegar coisas na
message queue.
Promises que são resolvidas antes da função corrente encerar serão executadas
logo após a função corrente.
Exemplo:
Loading Project
Glitch Tip!
Collaborate live with friends by inviting them to your project
Entendendo o process.nextTick()
Uma parte importante do event loop é o process.nextTick()
process.nextTick().
Toda vez que o event loop termina um ciclo, nós chamamos isso de tick.
process.nextTick(() => {
//faça algo
})
Esse é o jeito que nós podemos dizer à engine JS para processar uma função
assíncronamente (depois da função atual), mas o mais breve possível, sem
en leirar.
Use nextTick() quando você quer garantir que na próxima iteração do event
loop o código já tenha sido executado.
Entendendo setImmediate()
Quando você quer executar um trecho de código assíncronamente, mas o mais
rápido possível, uma opção é utilizar a função setImmediate() provida pelo
Node.js:
setImmediate(() => {
//faça algo
})
Timers do JavaScript
setTimeout()
setTimeout(() => {
// roda após 2 segundos
}, 2000)
setTimeout(() => {
// roda após 50 milisegundos
}, 50)
Essa sintaxe de ne uma nova função. Você pode chamar qualquer outra função
que quiser, ou passar o nome de uma função existente, e de nir os parâmetros:
// mudei de ideia :v
clearTimeout(id)
Delay de zero
setTimeout(() => {
console.log('depois ')
}, 0)
setInterval()
setInterval(() => {
// roda a cada 2 segundos
}, 2000)
A função abaixo roda a cada 2 segundos até que você a diga pra parar, usando
clearInterval, passando o identi cador retornado por aquele
clearInterval
setInterval:
setInterval
clearInterval(id)
setTimeout recursivo
O setInterval inicia uma função a cada n milisegundos, sem levar em
consideração quando uma função nalizou sua execução.
Para evitar isso, você pode agendar um setTimout recursivo para ser chamado
quando a função de callback naliza:
setTimeout(myFunction, 1000)
}
setTimeout(myFunction, 1000)
Assincronicidade em Linguagens de
Programação
Computadores são assíncronos por de nição.
Não irei muito a fundo no conceito, mas só tenha em mente que é normal para
programas serem assíncronos e pararem a execução até que precisem de
atenção, permitindo ao computador executar outras coisas nesse meio tempo.
Quando um programa está esperando por uma resposta da rede, ele não pode
parar o processador até que a requisição nalize.
Linhas de código são executadas em séries, uma após a outra, por exemplo:
const a = 1
const b = 2
const c = a * b
console.log(c)
doSomething()
Mas o JavaScript nasceu dentro dos browsers, sua função principal, desde o
começo, era responder às interações do usuário, como onClick
onClick,
onChange, onSubmit e etc. Como isso pode ser feito com um
onMouseOver, onChange
onMouseOver
modelo programático síncrono?
Callbacks
Não tem como você saber quando um usuário vai clicar em um botão. Então,
você de ne uma função para lidar com o evento de click. Essa função será
chamada quando o evento for acionado:
document.getElementById('button').addEventListener('click', ()
// item clicado
})
window.addEventListener('load', () => {
// window carregou
// faça o que quiser
})
setTimeout(() => {
// roda após 2 segundos
}, 2000)
Requisições XHR também aceitam uma callback, nesse exemplo ao passar uma
função para uma propriedade que será chamada quando um evento em
particular ocorrer (nesse caso, o estado da requisição mudar):
window.addEventListener('load', () => {
document.getElementById('button').addEventListener('click',
setTimeout(() => {
items.forEach(item => {
// seu código aqui
})
}, 2000)
})
})
Esse é só um exemplo simples com 4 níveis de aninhamento, mas eu já vi
códigos com muito mais níveis e não é nem um pouco divertido.
Alternativas à callbacks
A partir do ES6, o JavaScript introduziu várias funcionalidades que nos ajudam
a lidar com código assíncrono sem o uso de callbacks: Promises (ES6) e
Async/Await (ES2017).
Promises no JavaScript
Introdução a Promises
Loading Project
Glitch Tip!
Search for and add third party libraries in package.json
Funções async usam promises por baixo dos panos, então entender como
promises funcionam é fundamental para entender como async e await
funcionam.
Uma vez que a promise tenha sido chamada, ela inicia em um estado pendente
(pending). Isso signi ca que a função que a chamou continua executando,
enquanto a promise estiver pendente até que se resolva, retornando à função
que a invocou os dados que foram requisitados.
Battery API
Fetch API
Service Workers
Um exemplo mais comum que você pode encontrar pois aí é uma técnica
chamada Promisifying (promissi car). Essa técnica é um jeito de poder usar
uma função JavaScript clássica que recebe uma callback, e retornar uma
promise:
const fs = require('fs')
getFile('/etc/passwd')
.then(data => console.log(data))
.catch(err => console.error(err))
Agora vamos ver como uma promise pode ser consumida ou usada.
Encadeando promises
Uma promise pode ser retornada para outra promise, criando uma cadeia de
promises.
fetch('/todos.json')
.then(status) // note que a função `status` é na verdade
.then(json) // da mesma forma, a única diferença aqui é
.then(data => { // ... por isso que `data` aparece aqui com
console.log('Request succeeded with JSON response', data)
})
.catch(error => {
console.log('Request failed', error)
})
Nesse exemplo, nós chamamos fetch() para obter uma lita de items TODO do
arquivo todos.json localizado na raiz do domínio, e nós criamos uma cadeia
de promises.
Essa operação fará com que a cadeia de promises pule todas promises
encadeadas e pule diretamente para o catch() no nal, logando o texto
Request failed e a mensagem de erro.
.then((data) => {
console.log('Request succeeded with JSON response', data)
})
e nós simplesmente o logamos no console.
Tratando erros
No exemplo da seção anterior, nós tinhamos um catch que foi adicionado na
cadeia de promises.
// or
Cascateando erros
Orquestrando promises
Promise.all()
Examplo:
const f1 = fetch('/something.json')
const f2 = fetch('/something2.json')
Promise.all([f1, f2])
.then(res => {
console.log('Array of results', res)
})
.catch(err => {
console.error(err)
})
Promise.race() roda quando a primeira das promises que você passar for
resolvida, e roda a callback anexada apenas uma vez, com o resultado da
primeira promise resolvida.
Exemplo:
Erros comuns
UnhandledPromiseRejectionWarning
Isso signi ca que a promise que você chamou foi rejeitada, mas não tinha
nenhum catch preparado para tratar o erro. Adicione um catch depois do
then causador do erro para tratá-lo propriamente.
Programação assincrona moderna com
Async Await no Javascript
Introdução
O JavaScript evoluiu de callbacks para promises (ES2015) em um curto período
de tempo, e desde o ES2017, JavaScript assíncrono está ainda mais simples com
a sintaxe async/await.
Elas foram boas primitivas enquanto uma sintaxe melhor não surgia, então,
quando chegou a hora certa, obtivemos as funções async.
Elas fazem o código parecer síncrono, mas por baixo dos panos ele é assíncrono
e não bloqueante.
Um exemplo rápido
Esse é um exemplo bem simples de async/await sendo usado para rodar uma
função assíncronamente:
Loading Project
Glitch Tip!
Collaborate live with friends by inviting them to your project
This site is protected by reCAPTCHA and the Google Privacy Policy and
Terms of Service apply.
Mesmo que isso não seja feito tão explicitamente, internamente fará com que
retorne uma promise.
e o mesmo aqui:
const aFunction = async () => {
return Promise.resolve('test')
}
getFirstUserData()
getFirstUserData()
Loading Project
Glitch Tip!
Click “Show” to see your app
on é usado para adicionar uma função callback que será executada quando o
evento for acionado
eventEmitter.on('start', () => {
console.log('started')
})
Quando rodamos
eventEmitter.emit('start')
eventEmitter.emit('start', 23)
Múltipos argumentos:
eventEmitter.emit('start', 1, 100)
removeListener() / off()
off(): remove um escutador (listener) de um evento
Glitch Tip!
Search for and add third party libraries in package.json
No seguinte caso
res.statusCode = 200
nós de nimos a propriedade statusCode para 200, para indicar uma resposta
bem sucedida.
res.setHeader('Content-Type', 'text/plain')
res.end('Hello World\n')
res.on('data', d => {
process.stdout.write(d)
})
})
const options = {
hostname: 'whatever.com',
port: 443,
path: '/todos',
method: 'POST',
headers: {
'Content-Type': 'application/json',
'Content-Length': data.length
}
}
res.on('data', d => {
process.stdout.write(d)
})
})
req.write(data)
req.end()
O jeito mais simples de fazer uma requisição HTTP usando Node.js é usar a
biblioteca Axios:
axios
.post('https://whatever.com/todos', {
todo: 'Buy the milk'
})
.then(res => {
console.log(`statusCode: ${res.statusCode}`)
console.log(res)
})
.catch(error => {
console.error(error)
})
const options = {
hostname: 'whatever.com',
port: 443,
path: '/todos',
method: 'POST',
headers: {
'Content-Type': 'application/json',
'Content-Length': data.length
}
}
res.on('data', d => {
process.stdout.write(d)
})
})
req.write(data)
req.end()
axios.post('https://whatever.com/todos', {
todo: 'Buy the milk'
})
Esse é o código do servidor que vai receber a requisição:
app.use(
express.urlencoded({
extended: true
})
)
app.use(express.json())
Se você não está usando Express, e você quer fazer isso em Node.js raiz, terá
um pouco mais de trabalho, é claro, pois o Express abstrai muitas coisas pra
você.
O ponto chave pra se entender é que quando você inicializa um servidor HTTP
usando http.createServer()
http.createServer(), a callback é chamada quando o servidor
obtêm todos os cabeçalhos HTTP, mas não o body (corpo da requisição).
Então, nós devemos escutar pelo conteúdo do body a ser processado, e ele é
processado em chunks(pedaços).
Então para acessar os dados, assumindo que esperamos receber uma string,
nós devemos colocá-los em um array:
const fs = require('fs')
const fs = require('fs')
try {
const fd = fs.openSync('/Users/joe/test.txt', 'r')
} catch (err) {
console.error(err)
}
Node.js le stats
Todo arquivo vem com um conjunto de detalhes que nós podemos inspecionar
usando Node.js.
O Node.js também fornece um método síncrono, que bloqueia a thread até que
os detalhes do arquivo estejam prontos:
const fs = require('fs')
try {
const stats = fs.statSync('/Users/joe/test.txt')
} catch (err) {
console.error(err)
}
Muitas, incluindo:
Há outros métodos avançados, mas a maior parte do que você vai usar na
programação do dia a dia são esses.
const fs = require('fs')
fs.stat('/Users/joe/test.txt', (err, stats) => {
if (err) {
console.error(err)
return
}
stats.isFile() // true
stats.isDirectory() // false
stats.isSymbolicLink() // false
stats.size // 1024000 //= 1MB
})
/users/joe/file.txt
C:\users\joe\file.txt
Exemplo:
path.dirname(notes) // /users/joe
path.basename(notes) // notes.txt
path.extname(notes) // .txt
Você pode obter o nome do arquivo sem a extensão ao especi car um segundo
argumento no basename
basename:
path.normalize('/users/joe/..//test.txt') // /users/test.txt
const fs = require('fs')
const fs = require('fs')
try {
const data = fs.readFileSync('/Users/joe/test.txt', 'utf8')
console.log(data)
} catch (err) {
console.error(err)
}
Isso signi ca que arquivos grandes vão causar grandes impactos no consumo
de memória e na velocidade de execução do programa.
Nesse caso, uma opção melhor é ler o conteúdo do arquivo usando streams.
Exemplo:
const fs = require('fs')
const fs = require('fs')
Por padrão, essa API vai apagar o conteúdo do arquivo se ele existir. By default,
this API will replace the contents of the le if it does already exist.
Você pode modi car o comportamento padrão especi cando uma ag:
Usando streams
Todos esses métodos escrevem o conteúdo completo no arquivo antes de
retornarem o controle de volta ao programa (na versão assíncrona, isso
signi ca executar a callback)
const fs = require('fs')
const fs = require('fs')
const path = require('path')
fs.readdirSync(folderPath)
fs.readdirSync(folderPath).map(fileName => {
return path.join(folderPath, fileName)
})
const fs = require('fs')
const fs = require('fs')
try {
fs.renameSync('/Users/joe', '/Users/roger')
} catch (err) {
console.error(err)
}
Instale usando
e use-o assim:
const fs = require('fs-extra')
fs.remove(folder)
.then(() => {
//done
})
.catch(err => {
console.error(err)
})
ou com async/await:
O módulo fs
O módulo fs disponibiliza diversas funcionalidades úteis para acessar e
interagir com o le system.
const fs = require('fs')
Feito isso, você tem acesso a todos os métodos dele, o que inclui:
fs.open(): de ne o
fs.open() le mode
fs.stat() retorna o status do arquivo identi cado pelo nome que foi
fs.stat():
passado. Relacionado: fs.fstat()
fs.fstat(), fs.lstat()
fs.truncate() trunca o arquivo identi cado pelo nome que foi passado para
fs.truncate():
o tamanho especi cado. Relacionado: fs.ftruncate()
fs.utimes(): muda a timestamp do arquivo identi cado pelo nome que foi
fs.utimes()
passado. Relacionado: fs.futimes()
Uma coisa peculiar sobre o módulo fs é que todos os métodos são assíncronos
por padrão, mas eles também podem rodar de forma síncrona adicionando
Sync no nome.
Por exemplo:
fs.rename()
fs.renameSync()
fs.write()
fs.writeSync()
const fs = require('fs')
// feito
})
Uma API síncrona pode ser usada com um bloco de try/catch para tratar erros:
const fs = require('fs')
try {
fs.renameSync('before.json', 'after.json')
// feito
} catch (err) {
console.error(err)
}
A principal diferença aqui é que a execução do seu script no segundo exemplo
vai bloquear a thread, até que a operação no arquivo seja bem-sucedida.
O módulo path
O módulo path disponibiliza diversas funcionalidades úteis para acessar e
interagir com o le system.
path.basename()
require('path').basename('/test/something') // something
require('path').basename('/test/something.txt') // something.t
require('path').basename('/test/something.txt', '.txt') // som
path.dirname()
path.extname()
require('path').extname('/test/something') // ''
require('path').extname('/test/something/file.txt') // '.txt'
path.isAbsolute()
require('path').isAbsolute('/test/something') // true
require('path').isAbsolute('./test/something') // false
path.join()
path.normalize()
Tenta calcular o caminho correto quando ele contêm especi cadores relativos
como . ou ..
.., ou barras duplas:
require('path').normalize('/users/joe/..//test.txt') // '/user
path.parse()
root a raiz
root:
Exemplo:
require('path').parse('/users/test.txt')
resulta em
{
root: '/',
dir: '/users',
base: 'test.txt',
ext: '.txt',
name: 'test'
}
path.relative()
require('path').relative('/Users/joe', '/Users/joe/test.txt')
require('path').relative('/Users/joe', '/Users/joe/something/t
path.resolve()
O Módulo OS
Esse módulo disponibiliza diversas funções que você pode usar para obter
informações do sistema operacional e do computador em que o programa está
executando, e interagir com ele.
const os = require('os')
os.arch()
os.cpus()
Exemplo:
[
{
model: 'Intel(R) Core(TM)2 Duo CPU P8600 @ 2.40GHz',
speed: 2400,
times: {
user: 281685380,
nice: 0,
sys: 187986530,
idle: 685833750,
irq: 0
}
},
{
model: 'Intel(R) Core(TM)2 Duo CPU P8600 @ 2.40GHz',
speed: 2400,
times: {
user: 282348700,
nice: 0,
sys: 161800480,
idle: 703509470,
irq: 0
}
}
]
os.endianness()
os.freemem()
os.homedir()
Exemplo:
'/Users/joe'
os.hostname()
os.loadavg()
Exemplo:
os.networkInterfaces()
Exemplo:
{ lo0:
[ { address: '127.0.0.1',
netmask: '255.0.0.0',
family: 'IPv4',
mac: 'fe:82:00:00:00:00',
internal: true },
{ address: '::1',
netmask: 'ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff',
family: 'IPv6',
mac: 'fe:82:00:00:00:00',
scopeid: 0,
internal: true },
{ address: 'fe80::1',
netmask: 'ffff:ffff:ffff:ffff::',
family: 'IPv6',
mac: 'fe:82:00:00:00:00',
scopeid: 1,
internal: true } ],
en1:
[ { address: 'fe82::9b:8282:d7e6:496e',
netmask: 'ffff:ffff:ffff:ffff::',
family: 'IPv6',
mac: '06:00:00:02:0e:00',
scopeid: 5,
internal: false },
{ address: '192.168.1.38',
netmask: '255.255.255.0',
family: 'IPv4',
mac: '06:00:00:02:0e:00',
internal: false } ],
utun0:
[ { address: 'fe80::2513:72bc:f405:61d0',
netmask: 'ffff:ffff:ffff:ffff::',
family: 'IPv6',
mac: 'fe:80:00:20:00:00',
scopeid: 8,
internal: false } ] }
os.platform()
darwin
freebsd
linux
openbsd
win32
…outros
os.release()
os.tmpdir()
os.totalmem()
os.type()
Linux
Darwin no macOS
Windows_NT no Windows
os.uptime()
os.userInfo()
Retorna um objeto contendo o username corrente, uid
uid, gid shell, e
gid, shell
homedir
O módulo de eventos
O móduo events nos disponibiliza a classe EventEmitter, que é essencial para
trabalhar com eventos no Node.js.
emitter.addListener()
emitter.emit()
emitter.eventNames()
Retorna um array de string que representa os eventos regstrados no objeto
EventEmitter atual:
door.eventNames()
emitter.getMaxListeners()
door.getMaxListeners()
emitter.listenerCount()
door.listenerCount('open')
emitter.listeners()
door.listeners('open')
emitter.off()
Alias para emitter.removeListener() adicionado no Node.js 10
emitter.on()
Uso:
door.on('open', () => {
console.log('Door was opened')
})
emitter.once()
Adiciona uma função callback que será chamada quando um evento for emitido
pela primeira vez depois de registrado. Essa callback só será chamada uma vez.
ee.once('my-event', () => {
// chama a função callback uma vez
})
emitter.prependListener()
emitter.removeAllListeners()
door.removeAllListeners('open')
emitter.removeListener()
Remove um listener em especí co. Você pode fazer isso salvando a função
callback em uma variável, quando adicionada, ela pode ser referenciada mais
tarde:
emitter.setMaxListeners()
door.setMaxListeners(50)
Módulo HTTP
O módulo HTTP é um módulo essencial para aplicações de rede em Node.js.
Properties
http.METHODS
> require('http').METHODS
[ 'ACL',
'BIND',
'CHECKOUT',
'CONNECT',
'COPY',
'DELETE',
'GET',
'HEAD',
'LINK',
'LOCK',
'M-SEARCH',
'MERGE',
'MKACTIVITY',
'MKCALENDAR',
'MKCOL',
'MOVE',
'NOTIFY',
'OPTIONS',
'PATCH',
'POST',
'PROPFIND',
'PROPPATCH',
'PURGE',
'PUT',
'REBIND',
'REPORT',
'SEARCH',
'SUBSCRIBE',
'TRACE',
'UNBIND',
'UNLINK',
'UNLOCK',
'UNSUBSCRIBE' ]
http.STATUS_CODES
> require('http').STATUS_CODES
{ '100': 'Continue',
'101': 'Switching Protocols',
'102': 'Processing',
'200': 'OK',
'201': 'Created',
'202': 'Accepted',
'203': 'Non-Authoritative Information',
'204': 'No Content',
'205': 'Reset Content',
'206': 'Partial Content',
'207': 'Multi-Status',
'208': 'Already Reported',
'226': 'IM Used',
'300': 'Multiple Choices',
'301': 'Moved Permanently',
'302': 'Found',
'303': 'See Other',
'304': 'Not Modified',
'305': 'Use Proxy',
'307': 'Temporary Redirect',
'308': 'Permanent Redirect',
'400': 'Bad Request',
'401': 'Unauthorized',
'402': 'Payment Required',
'403': 'Forbidden',
'404': 'Not Found',
'405': 'Method Not Allowed',
'406': 'Not Acceptable',
'407': 'Proxy Authentication Required',
'408': 'Request Timeout',
'409': 'Conflict',
'410': 'Gone',
'411': 'Length Required',
'412': 'Precondition Failed',
'413': 'Payload Too Large',
'414': 'URI Too Long',
'415': 'Unsupported Media Type',
'416': 'Range Not Satisfiable',
'417': 'Expectation Failed',
'418': 'I\'m a teapot',
'421': 'Misdirected Request',
'422': 'Unprocessable Entity',
'423': 'Locked',
'424': 'Failed Dependency',
'425': 'Unordered Collection',
'426': 'Upgrade Required',
'428': 'Precondition Required',
'429': 'Too Many Requests',
'431': 'Request Header Fields Too Large',
'451': 'Unavailable For Legal Reasons',
'500': 'Internal Server Error',
'501': 'Not Implemented',
'502': 'Bad Gateway',
'503': 'Service Unavailable',
'504': 'Gateway Timeout',
'505': 'HTTP Version Not Supported',
'506': 'Variant Also Negotiates',
'507': 'Insufficient Storage',
'508': 'Loop Detected',
'509': 'Bandwidth Limit Exceeded',
'510': 'Not Extended',
'511': 'Network Authentication Required' }
http.globalAgent
Aponta para a instância global do objeto Agente, que é uma instÂncia da classe
http.Agent.
http.Agent
Methods
http.createServer()
Uso:
http.request()
Faz uma requisição HTTP para um servidor, criando uma instância da classe
http.ClientRequest.
http.ClientRequest
http.get()
Classes
O módulo HTTP provê 5 classes:
http.Agent
http.ClientRequest
http.Server
http.ServerResponse
http.IncomingMessage
http.Agent
Esse objeto garante que toda requisição feita ao servidor seja en leirada e um
único socket seja reusado.
http.ClientRequest
http.Server
Uma vez que você tenha um objeto server, você pode acessar os métodos dele:
http.ServerResponse
Você sempre deve chamar o método end() na callback, que fecha a response, a
mensagem está completa e o servidor pode enviá-la ao client. Deve ser
chamado em cada response.
Para enviar os dados ao client pelo body da response, você usa write().
write() Ele
enviará os dados armazenados em bu er para a stream de resposta HTTP.
response.statusCode = 500
response.statusMessage = 'Internal Server Error'
http.IncomingMessage
Bu ers no Node.js
O que é um bu er?
Um bu er é uma área de memória. Desenvolvedores JavaScript não são
familiarizados com esse conceito, muito menos que desenvolvedores C, C++ ou
Go (ou qualquer programador que use uma linguagem de programação de
sistema), que interagem com memória diariamente.
?
Por que precisamos de um bu er?
Bu ers foram introduzidos para ajudar desenvolvedores a lidar com dados
binários, em um ecossistema que tradicionalmente só lida com strings em vez
de binários.
Como criar um bu er
Um bu er é criado usando os métodos Buffer.from(), Buffer.alloc() e
Buffer.from() Buffer.alloc(),
Buffer.allocUnsafe().
Buffer.allocUnsafe()
Buffer.from(array)
Buffer.from(buffer)
Buffer.from(string[, encoding])
Usando um bu er
Acessando o conteúdo de um bu er
Esses números são o Código Unicode que identi ca o caracter naquela posição
do bu er (H => 72, e => 101, y => 121)
console.log(buf.toString())
Mudando o conteúdo de um bu er
Assim como você pode acessar um bu er com uma sintaxe de array, você
também pode de nir os conteúdos do bu er dessa mesma forma:
Copiando um bu er
Por padrão você copia o bu er inteiro. Mais 3 parâmetros deixam você de nir a
posição inicial, a posição nal, e o comprimento do novo bu er:
Fatiando um bu er
Se você quer criar uma visualização parccial de um bu er, você pode criar uma
fatia (slice). Uma fatia não é uma cópia: o bu er original ainda é a fonte de
verdade. Se ele mudar, sua fatia também muda.
Node.js Streams
O módulo stream provê a fundação da qual todas APIs de streaming são feitas.
Todas streams são instâncias do EventEmitter
Porquê streams
Streams basicamente nos dão duas grandes vantagens sobre outros métodos
de manipulação de dados:
Um exemplo de stream
Um exemplo típico é ler arquivos de um disco.
Em vez de esperar até que o arquivo seja completamente lido, nós começamos
a “streamá-lo” para o client HTTP assim que tivermos chunks de dados
prontos para serem enviados.
pipe()
O exemplo acima usa stream.pipe(res)
stream.pipe(res): o método pipe() é chamado na
stream de arquivo.
O que esse código faz? Ele pega a origem, e canaliza para um destino.
O valor retornado pelo método pipe() é a stream de destino, que é algo muito
conveniente pois nos permite encadear múltiplas chamadas pipe(),
pipe() desse
jeito:
src.pipe(dest1).pipe(dest2)
src.pipe(dest1)
dest1.pipe(dest2)
Readable: uma stream de onde você pode canalizar, mas não canalizar dados
Readable
nela (você pode receber dados, mas não pode enviar dados). Quando você
coloca dados em uma stream de leitura, os dados são bu erizados, até que um
consumer comece a ler os dados.
Writable uma stream em que você pode canalizar dados, mas não obter
Writable:
dados dela (você pode enviar dados, mas não pode receber).
Duplex: uma stream em que você pode tanto canalizar dados quando obtê-
Duplex
los, basicamente uma combinação de uma stream Readable e uma Writable
readableStream._read = () => {}
Agora que a stream está inicializada, nós podemos enviar dados a ela:
readableStream.push('hi!')
readableStream.push('ho!')
process.stdin.pipe(writableStream)
readableStream.pipe(writableStream)
readableStream.push('hi!')
readableStream.push('ho!')
readableStream.on('readable', () => {
console.log(readableStream.read())
})
Como enviar dados para uma stream de
escrita
Usando o método write() da stream:
writableStream.write('hey!\n')
readableStream.pipe(writableStream)
readableStream.push('hi!')
readableStream.push('ho!')
writableStream.end()
export NODE_ENV=production
Por exemplo, em uma aplicação Express, você pode usar isso para de nir o
errorHandler de acordo com o ambiente:
Criando exceções
Uma exceção é crianda usando a palavra reservada throw
throw:
throw value
Objetos de erro
Um objeto de erro é um objeto que é uma instância do objeto Error, ou que
extenda a classe Error, fornecida pelo módulo nativo Error:
ou
Tratando exceções
Um bloco try/
try catch é um tratador de exceções.
Qualquer exceção lançada nas linhas que incluem o bloco try serão tratadas
no bloco catch correspondente:
try {
// linhas de código
} catch (e) {}
Você pode adicionar múltiplos blocos, que podem tratar diferentes tipos de
erros.
Pegando exceções não capturadas
Se uma exceção não capturada for lançada durante a execução do seu
programa, ele irá crashar.
doSomething1()
.then(doSomething2)
.then(doSomething3)
.catch(err => console.error(err))
Como você sabe quando o erro ocorreu? Você na verdade não sabe, mas você
pode tratar erros em cada uma das funções que chamar ( doSomethingX),
doSomethingX e
dentro do catch lançar um novo erro, que chamará o catch exterior:
Para ser possível tratar erros localmente sem tratá-los na função que
chamamos, nós podemos quebar a corrente, você pode criar uma função em
cada then e processar a exceção:
doSomething1()
.then(() => {
return doSomething2().catch(err => {
// trata o erro
throw err // quebre a corrente!
})
})
.then(() => {
return doSomething2().catch(err => {
// trata o erro
throw err // quebra a corrente!
})
})
.catch(err => console.error(err))
Nós não temos tanto luxo quando logamos algo no console, porque isso vai
retornar o objeto para o shell se você rodar o programa Node.js manualmente,
ou para um arquivo de log. Você obtêm uma representação do objeto em
formato de string.
Agora, tudo ca bem até um certo nível de aninhamento. Depois de dois níveis
de aninhamento, o Node.js desiste e imprime [Object] como um placeholder:
const obj = {
name: 'joe',
age: 35,
person1: {
name: 'Tony',
age: 50,
person2: {
name: 'Albert',
age: 21,
person3: {
name: 'Peter',
age: 23
}
}
}
}
console.log(obj)
{
name: 'joe',
age: 35,
person1: {
name: 'Tony',
age: 50,
person2: {
name: 'Albert',
age: 21,
person3: [Object]
}
}
}
require('util').inspect.defaultOptions.depth = null
console.log(obj)
mas o problema é que objetos aninhados com mais de 2 níveis cam
plani cados, e isso pode ser um problema com objetos complexos.
Referências
Revisado, Editado e baseado na documentação o cial do NodeJS, da qual
possue licença MIT, que permite a livre redistribuição.
Se você quiser dar o proximo passo para ser um dev pro ssional, eu
posso te mentorar! é só você clicar aqui.