Estamos compartilhando a tradução do artigo, que contém detalhes sobre os novos recursos da 15ª versão do Node.js.
A versão 15 do Node.js foi lançada em 20 de outubro de 2020. As principais mudanças incluem:
- modo de lançamento em desvios não tratados
- recursos de linguagem V8 8.6
- NPM 7
- suporte QUIC experimental
- N-API Versão 7
- finalização da API Async Local Storage
Vamos examinar mais de perto o que são essas inovações e como podem ser usadas.
Usando NVM para Visão Geral do Nó
No artigo anterior, examinamos as instruções para usar NVM (Node Version Manager) para gerenciar versões de Node.js e NPM. Temos o Node.js 12.16.0 e o NPM 6.14.8 instalados em nosso ambiente. Ao executar o nvm install node , instalamos o Node.js 15.4.0 e o NPM7.0.15.
Temos duas janelas abertas, uma com Node.js 12 e outra com Node.js 15.
Na janela do node12 :
$ nvm use 12 Now using node v12.16.0 (npm v6.14.8)
Na janela node15 :
$ nvm use 15 Now using node v15.4.0 (npm v7.0.15)
Agora podemos investigar esta versão.
Modo de lançamento na rejeição de promessa não tratada
O evento unhandledRejection é gerado sempre que uma promessa é rejeitada e um manipulador de erro não é anexado à promessa durante o loop de eventos. A partir do Node.js 15, o modo padrão para unhandledRejection foi alterado de warn para throw . No modo de lançamento , se o gancho unhandledRejection não estiver definido, o unhandledRejection será lançado como uma exceção não detectada pelo método catch .
Crie um programa para rejeitar a promessa com uma mensagem de erro:
function myPromise() {
new Promise((_, reject) =>
setTimeout(
() =>
reject({
error: 'The call is rejected with an error',
}),
1000
)
).then((data) => console.log(data.data));
}
myPromise();
Quando você executa este código em uma janela node12 , uma longa mensagem de aviso é exibida:
$ node myPromise.js
(node:79104) UnhandledPromiseRejectionWarning: #<Object>
(node:79104) UnhandledPromiseRejectionWarning: Unhandled promise rejection. This error originated either by throwing inside of an async function without a catch block, or by rejecting a promise which was not handled with .catch(). To terminate the node process on unhandled promise rejection, use the CLI flag `--unhandled-rejections=strict` (see https://nodejs.org/api/cli.html#cli_unhandled_rejections_mode). (rejection id: 1)
(node:79104) [DEP0018] DeprecationWarning: Unhandled promise rejections are deprecated. In the future, promise rejections that are not handled will terminate the Node.js process with a non-zero exit code.Users that have an unhandledRejection hook should see no change in behavior, and it’s still possible to switch modes using the --unhandled-rejections=mode process flag.
A execução deste código na janela node15 gera um erro UnhandledPromiseRejection :
$ node myPromise.js
node:internal/process/promises:227
triggerUncaughtException(err, true /* fromPromise */);
^[UnhandledPromiseRejection: This error originated either by throwing inside of an async function without a catch block, or by rejecting a promise which was not handled with .catch(). The promise rejected with the reason "#<Object>".] {
code: 'ERR_UNHANDLED_REJECTION'
}
Adicione um manipulador de erros ao branch then no código abaixo ( .catch (( erro ) => console.log ( erro .error)) também funciona).
function myPromise() {
new Promise((_, reject) =>
setTimeout(
() =>
reject({
error: 'The call is rejected with an error',
}),
1000
)
).then(
(data) => console.log(data.data),
(error) => console.log(error.error)
);
}
myPromise();
Agora o código é executado corretamente em ambas as janelas ( node12 e node15 ):
$ node myPromise.js The call is rejected with an error
É recomendado escrever um manipulador de erros para promessas. No entanto, pode haver casos em que os erros não são detectados pelo método catch. É recomendável configurar o gancho unhandledRejection para detectar erros em potencial.
function myPromise() {
new Promise((_, reject) =>
setTimeout(
() =>
reject({
error: 'The call is rejected with an error',
}),
1000
)
).then((data) => console.log(data.data));
}
myPromise();
process.on('unhandledRejection', (reason, promise) => {
console.log('reason is', reason);
console.log('promise is', promise);
// Application specific logging, throwing an error, or other logic here
});
O gancho unhandledRejection funciona tanto no Node.js 12 quanto no Node.js 15. Depois de instalado, o unhandledRejection é tratado conforme necessário.
$ node myPromise.js
reason is { error: 'The call is rejected with an error' }
promise is Promise { <rejected> { error: 'The call is rejected with an error' } }
V8 8.6 Novos recursos de linguagem
V8, mecanismo JavaScript, atualizado de 8.4 para 8.6. versão. Além de vários ajustes para melhorar o desempenho, o novo V8 tem os seguintes recursos:
- Promise.any () e AggregateError (de V8 8.5)
- aguarde setTimeout e AbortController (experimental)
- String.prototype.replaceAll () (a partir de V8 8.5)
- Operadores de atribuição lógica && = , || = e ?? = (a partir de V8 8.5)
Promise.any () e AggregateError
Primeiro, vamos dar uma olhada no método Promise.all () existente .
Promise.all () pega um iterável de promessas como entrada e retorna uma única promessa, que é executada como uma matriz dos resultados das promessas de entrada.
O programa a seguir chama Promise.all () em duas promessas resolvidas:
function myPromise(delay) {
return new Promise((resolve) =>
setTimeout(
() =>
resolve({
data: The data from ${delay} ms delay,
}),
delay
)
);
}
async function getData() {
try {
const data = await Promise.all([myPromise(5000), myPromise(100)]);
console.log(data);
} catch (error) {
console.log(error);
}
}
getData();
Promise.all () retorna uma promessa que será cumprida quando todas as promessas de entrada forem resolvidas ou se o iterável não contiver promessas:
$ node myPromise.js
[
{ data: 'The data from 5000 ms delay' },
{ data: 'The data from 100 ms delay' }
]
O programa a seguir chama Promise.all () em duas promessas rejeitadas.
function myPromise(delay) {
return new Promise((_, reject) =>
setTimeout(
() =>
reject({
error: The error from ${delay} ms delay,
}),
delay
)
);
}
async function getData() {
try {
const data = await Promise.all([myPromise(5000), myPromise(100)]);
console.log(data);
} catch (error) {
console.log(error);
}
}
getData();
Promise.all () rejeita imediatamente qualquer rejeição da promessa de entrada ou qualquer erro no momento da execução, retornando uma mensagem sobre este erro:
$ node myPromise.js
{ error: 'The error from 100 ms delay' }
Promise.any () é um novo método em Node.js 15. É o oposto de Promise.all () . Promise.any () aceita um iterável contendo objetos Promise. E, assim que uma das Promessas no iterável for bem-sucedida, o método retornará uma única promessa com o valor da promessa cumprida.
O programa a seguir chama Promise.any () em duas promessas resolvidas:
function myPromise(delay) {
return new Promise((resolve) =>
setTimeout(
() =>
resolve({
data: The error from ${delay} ms delay,
}),
delay
)
);
}
async function getData() {
try {
const data = await Promise.any([myPromise(5000), myPromise(100)]);
console.log(data);
} catch (error) {
console.log(error);
console.log(error.errors);
}
}
getData();
Promise.any () retorna a primeira promessa resolvida:
$ node myPromise.js
{ data: 'The error from 100 ms delay' }
O programa a seguir chama Promise.any () em duas promessas rejeitadas:
function myPromise(delay) {
return new Promise((_, reject) =>
setTimeout(
() =>
reject({
error: The error from ${delay} ms delay,
}),
delay
)
);
}
async function getData() {
try {
const data = await Promise.any([myPromise(5000), myPromise(100)]);
console.log(data);
} catch (error) {
console.log(error);
console.log(error.errors);
}
}
getData();
Se as promessas no iterável falharem, ou seja, todas as promessas feitas são rejeitadas, a promessa retornada é rejeitada com AggregateError , uma nova subclasse de Error que agrupa erros individuais.
$ node myPromise.js
[AggregateError: All promises were rejected]
[
{ error: 'The error from 5000 ms delay' },
{ error: 'The error from 100 ms delay' }
]
Aguarde setTimeout e AbortController
Nos exemplos anteriores, usamos setTimeout dentro de uma chamada de promessa.
SetTimeout em WindowOrWorkerGlobalScope usa um retorno de chamada. No entanto, timers / promises fornecem uma versão prometida de setTimeout que pode ser usada com async / await.
const { setTimeout } = require('timers/promises');
async function myPromise(delay) {
await setTimeout(delay);
return new Promise((resolve) => {
resolve({
data: The data from ${delay} ms delay,
});
});
}
async function getData() {
try {
const data = await Promise.any([myPromise(5000), myPromise(100)]);
console.log(data);
} catch (error) {
console.log(error);
console.log(error.errors);
}
}
getData();
AbortController é um objeto JavaScript que permite abortar uma ou mais solicitações da web à vontade. Fornecemos exemplos de uso do AbortController em outro artigo sobre useAsync .
Ambos aguardam setTimeout e AbortController são recursos experimentais.
String.prototype.replaceAll ()
Vamos dar uma olhada no método String.prototype.replace () existente .
replace () retorna uma nova string com algumas ou todas as correspondências de padrão substituídas com o substituto. O padrão pode ser uma string ou uma expressão regular. O espaço reservado pode ser uma string ou uma função chamada para cada correspondência.
Se o padrão for uma string, apenas a primeira ocorrência será substituída.
'20+1+2+3'.replace('+', '-');
Usar este operador resultará em “20–1 + 2 + 3” .
Para substituir todos os "+" por "-", você precisa usar uma expressão regular.
'20+1+2+3'.replace(/\+/g, '-');
Usar o operador acima resultará em “20-1-2-3” .
O método replaceAll () é novo no Node.js 15. Ao usá-lo, não precisamos usar uma expressão regular. Este método retorna uma nova string com todas as correspondências de padrão substituídas pelo espaço reservado. O padrão pode ser uma string ou uma expressão regular, e o marcador de posição pode ser uma string ou uma função chamada para cada correspondência.
Graças ao método replaceAll () , não precisamos usar uma expressão regular para substituir todos os "+" por "-".
'20+1+2+3'.replaceAll('+', '-');
A execução deste operador dá “20-1-2-3” .
Operadores de atribuição lógica && =, || = e ?? =
O operador de atribuição lógica AND ( x && = y ) realiza uma operação de atribuição apenas se x for verdadeiro.
x && = y é equivalente a x && (x = y) , mas não equivalente a x = x && y .
let x = 0;
let y = 1;
x &&= 0; // 0
x &&= 1; // 0
y &&= 1; // 1
y &&= 0; // 0
O operador de atribuição lógica OR (x || = y) realiza uma operação de atribuição apenas se x for falso.
x || = y é equivalente ax || (x = y) mas não equivalente a x = x || a .
let x = 0;
let y = 1;
x ||= 0; // 0
x ||= 1; // 1
y ||= 1; // 1
y ||= 0; // 1
O operador de atribuição lógica nullish (x ?? = y) realiza uma operação de atribuição apenas se x for NULL ( nulo ou indefinido ).
x ?? = y é equivalente ax ?? (x = y) , e não equivalente ax = x ?? a .
let x = undefined;
let y = '';
x ??= null; // null
x ??= 'a value'; // "a value"
y ??= undefined; // ""
y ??= null; // ""
Outras mudanças
Além do modo de lançamento em rejeição de promessa não tratada e novos recursos de linguagem V8 8.6, Node.js 15 tem as seguintes alterações:
NPM 7 : muitas alterações, incluindo instalação automática de dependências de pares, melhorias em pacotes e arquivos yarn.lock, suporte a espaço de trabalho , etc. Tudo isso é descrito neste artigo por referência .
QUIC : suporte experimental para a camada de transporte UDP, que é o protocolo principal para HTTP / 3. O QUIC inclui segurança integrada com TLS 1.3, controle de fluxo, correção de erros, migração de conexão e multiplexação.
N-API Versão 7: API para criar addons personalizados. É independente do tempo de execução JavaScript subjacente e é compatível com Node.js.
Aprimoramento da API Async Local Storage : Fornece a capacidade de registro mais moderno e análise de recursos para aplicativos de grande escala.
Conclusão
A nova versão do Node.js 15 possui um grande número de novos recursos e melhorias, incluindo algumas bastante significativas.
Experimente a nova versão e prepare-se para atualizar projetos.
Obrigado pela atenção! Espero que o artigo tenha sido útil para você.