É sempre importante nos desafiarmos e irmos além do que é pedido nos exercícios, porque isso ajuda muito a testar e expandir nossos limites. Com isso, posso dizer: "Que exercício desafiador!"
Ao tentar aplicar conceitos vistos nas aulas de funções:
Aprendi como funciona o readline usando async/await em vez do padrão de callbacks.
Aprendi que, para utilizar await, a função precisa retornar uma Promise, e que o await serve justamente para “esperar” a resolução dessa Promise antes de continuar o fluxo.
Entendi também que, ao criar Promises, precisamos passar uma função executora que recebe resolve (e opcionalmente reject). O resolve finaliza a Promise com sucesso, enquanto o reject indica erro.
Escrevi de cabeça a expressão RegEx /^[a-zA-ZÀ-ÿ\s-]+$/, e lembrei como filtrar os termos com o uso de .test(), que retorna true ou false dependendo da validação.
Evitei repetição de código ao perceber que várias entradas precisavam do mesmo tipo de validação e criei uma função única para tratar entradas inválidas de forma centralizada.
Essa função utiliza
throw new Error, que aprendi funcionar como uma interrupção imediata do fluxo de execução, desviando o controle para o catch.Também utilizei busca em array (
find) como alternativa mais elegante ao uso de vários if/else para classificar os intervalos de consumo de energia.Foi a primeira vez que utilizei
async/awaitde forma completa em um projeto, e confesso que a compreensão inicial exigiu atenção, mas ajudou muito a entender melhor o fluxo assíncrono.Utilizei
try/catchpara tratar erros lançados pela validação e garantir que o programa não quebrasse de forma inesperada, além definallypara garantir que orl.close()fosse executado independentemente de sucesso ou erro.Por fim, aprendi que posso usar uma função
main()para encapsular toda a lógica assíncrona com await.
Segue minha versão:
import { createInterface } from "readline";
const rl = createInterface({
input: process.stdin,
output: process.stdout,
});
const perguntar = (texto) => {
return new Promise((resolve) => {
rl.question(texto, resolve);
});
};
const validarNome = (input) => {
const nome = input.trim();
const nomeValido = /^[a-zA-ZÀ-ÿ\s-]+$/.test(nome) && nome.length > 1;
return nomeValido ? nome : null;
};
const validarNum = (input) => {
const num = Number(input);
if (Number.isNaN(num) || num < 0) return null;
return num;
};
const tratarInvalido = (dado) => {
if (dado === null) {
rl.close();
throw new Error("Dado inválido");
}
return dado;
};
const calcularConsumo = (potencia, horasPorDia) => {
const consumo = (potencia * horasPorDia * 30) / 1000;
return consumo;
};
const classificarConsumo = (consumo) => {
const faixas = [
{ limite: 49, classificacao: "baixo consumo" },
{ limite: 199, classificacao: "consumo moderado" },
{ limite: Infinity, classificacao: "alto consumo" },
];
return faixas.find((faixa) => consumo < faixa.limite).classificacao;
};
const exibirResumo = (nomeAparelho, consumo, classificacao) => {
console.log(
`${nomeAparelho} tem consumo de ${consumo}kWh/mês e possui classificação de ${classificacao}.`,
);
};
const main = async () => {
try {
const nomeAparelho = tratarInvalido(
validarNome(await perguntar("Nome do Eletrônico\n> ")),
);
const potencia = tratarInvalido(
validarNum(await perguntar("Potência (em Watts)\n> ")),
);
const horasPorDia = tratarInvalido(
validarNum(await perguntar("Horas de uso por dia\n> ")),
);
const consumo = calcularConsumo(potencia, horasPorDia);
const classificacao = classificarConsumo(consumo);
exibirResumo(nomeAparelho, consumo, classificacao);
} catch (err) {
console.log("Entrada inválida. Tente novamente.");
} finally {
rl.close();
}
};
main();