Container de Injeção de Dependência para JavaScript (Node.js) — Awilix

Treinador Online de Python para Iniciantes

Aprenda Python facilmente sem sobrecarga teórica. Resolva tarefas práticas com verificação automática e escreva código diretamente no navegador.

Start Course

Container de Injeção de Dependência para JavaScript (Node.js) — Awilix



No desenvolvimento moderno com Node.js, a pureza da arquitetura e a testabilidade do código estão em primeiro plano. Uma das ferramentas-chave para alcançar esses objetivos é a injeção de dependências (Dependency Injection, DI). A biblioteca Awilix fornece um container DI poderoso, performático e flexível para JavaScript e TypeScript, ideal para aplicações server-side em Node.js. Neste artigo, vamos detalhar como usar Awilix para gerenciar dependências, melhorar a modularidade e simplificar os testes.



O que é Injeção de Dependência e para que serve um container?



Injeção de Dependência é um padrão de projeto no qual um objeto recebe suas dependências externamente, em vez de criá-las ele mesmo. Isso implementa o princípio Inversion of Control (IoC). Um container é uma ferramenta que automatiza o processo de criação e fornecimento dessas dependências. Em vez de criar manualmente instâncias de classes e passá-las umas para as outras, você descreve as regras de montagem no container, e ele resolve todas as cadeias de dependências.



Principais vantagens de usar um container DI:

  • Redução do acoplamento do código: Módulos dependem de abstrações, não de implementações concretas.
  • Simplificação dos testes: Fácil substituir serviços reais por mocks durante testes unitários.
  • Gerenciamento centralizado: Toda a configuração de dependências fica em um só lugar, facilitando a refatoração.
  • Gerenciamento do ciclo de vida: O container pode controlar por quanto tempo um objeto vive — uma única instância para toda a aplicação (singleton) ou uma nova a cada requisição.


Instalação do Awilix



Para começar, instale a biblioteca via npm:

npm install awilix


Awilix não possui dependências externas e funciona tanto com módulos CommonJS quanto ESM.



Conceitos principais do Awilix



Awilix é construído em torno de alguns conceitos-chave:

  • Container (contêiner): O objeto principal que armazena e fornece as dependências.
  • Registration (registro): O processo de associar um nome (token) a uma fábrica, classe ou valor.
  • Resolver (resolvedor): Objeto que define como criar ou obter a dependência. Por exemplo, asClass(), asFunction(), asValue().
  • Lifetime (tempo de vida): Indica quantas vezes o objeto será criado: ScopedLifeTime (uma vez por escopo), SingletonLifeTime (uma vez durante toda a execução) ou TransientLifeTime (sempre uma nova instância).


Exemplo de uso: serviço para trabalhar com usuários



Vamos considerar um exemplo simples. Suponha que temos um banco de dados, um repositório de usuários e um serviço para a lógica de negócios.



1. Definindo as classes

// database.jsclass Database {    constructor() {        this.connection = 'Connected to DB';    }    query(sql) {        return `Result for: ${sql}`;    }}

// userRepository.jsclass UserRepository { constructor({ database }) { this.db = database; } findById(id) { return this.db.query(`SELECT * FROM users WHERE id = ${id}`); }}

// userService.jsclass UserService { constructor({ userRepository }) { this.repo = userRepository; } getUser(id) { return this.repo.findById(id); }}


Observe os construtores: eles recebem um objeto com as dependências. Esta é uma prática padrão para Awilix.



2. Configurando o container

const { createContainer, asClass, asValue, Lifetime } = require('awilix');

const container = createContainer();

// Registramos a

Recommendations