Provedores de serviço
Até agora, aprendemos como vincular dependências ao contêiner IoC.
Neste guia, damos um passo adiante para aprender sobre provedores de serviço e como distribuir pacotes que funcionam bem com o ecossistema AdonisJs.
Introdução
Sabemos que o método ioc.bind
pode ser usado para registrar vinculações. No entanto, ainda não definimos onde chamar esse método.
É aqui que os provedores de serviço entram em cena. Os provedores de serviço são classes ES6 puras com métodos de ciclo de vida que são usados para registrar e inicializar vinculações.
Por exemplo:
const { ServiceProvider } = require('@adonisjs/fold')
class MyProvider extends ServiceProvider {
register () {
// vinculações de registro
}
boot () {
// opcionalmente faça alguma configuração inicial
}
}
module.exports = MyProvider
- O método
register
é usado para registrar vinculações, e você nunca deve tentar usar nenhuma outra vinculação dentro desse método. - O método
boot
é chamado quando todos os provedores foram registrados e é o lugar certo para usar ligações existentes para inicializar o estado do aplicativo.
Por exemplo, adicionando uma visualização global:
boot () {
const View = this.app.use('Adonis/Src/View')
View.global('time', () => new Date().getTime())
}
pacote npm como um provedor de serviço
Vamos ver como podemos encapsular um pacote npm existente em um provedor de serviço.
NOTA
Não encapsular pacotes como lodash
em um provedor de serviço, pois ele pode ser usado diretamente e não requer nenhum processo de configuração.
Todos os provedores específicos do aplicativo vivem dentro do diretório providers
na raiz do seu aplicativo:
Estrutura de diretório
├── app
└── providers
└── Queue
└── index.js
└── Provider.js
└── start
Princípios
Vamos encapsular bee-queue como um provedor.
Aqui está um conjunto de princípios que queremos seguir:
- O usuário final não deve se preocupar em configurar o provedor de filas.
- Toda a configuração deve ficar dentro do arquivo
config/queue.js
. - Deve ser simples o suficiente para criar novas filas com uma configuração diferente.
Implementação
Vamos implementar o wrapper dentro do arquivo providers/Queue/index.js
:
// .providers/Queue/index.js
'use strict'
const BeeQueue = require('bee-queue')
class Queue {
constructor (Config) {
this.Config = Config
this._queuesPool = {}
}
get (name) {
/**
* Se já houver uma instância de queue, retorne-a
*/
if (this._queuesPool[name]) {
return this._queuesPool[name]
}
/**
* Ler configuração usando Config
* provedor
*/
const config = this.Config.get(`queue.${name}`)
/**
* Crie uma nova instância de fila e salve-a
* referência
*/
this._queuesPool[name] = new BeeQueue(name, config)
/**
* Retornar a instância de volta
*/
return this._queuesPool[name]
}
}
module.exports = Queue
A classe acima tem apenas um método chamado get
, que retorna uma instância da fila para um determinado nome de fila.
As etapas executadas pelo método get
são:
- Procure uma instância de um determinado nome de fila.
- Se uma instância não existir, leia a configuração usando o Provedor de configuração.
- Crie uma nova instância
bee-queue
e armazene dentro de um objeto para uso futuro. - Finalmente, retorne a instância.
A classe Queue
é pura, pois não tem nenhuma dependência rígida no framework e, em vez disso, depende da Injeção de Dependência para fornecer o Provedor de Configuração.
Provedor de serviço
Agora, vamos criar um provedor de serviço que faz a instanciação desta classe e a vincula ao contêiner IoC.
O código fica dentro de providers/Queue/Provider.js
:
// .providers/Queue/Provider.js
const { ServiceProvider } = require('@adonisjs/fold')
class QueueProvider extends ServiceProvider {
register () {
this.app.singleton('Bee/Queue', () => {
const Config = this.app.use('Adonis/Src/Config')
return new (require('.'))(Config)
})
}
}
module.exports = QueueProvider
Observe que this.app
é uma referência ao objeto ioc
, o que significa que em vez de chamar ioc.singleton
, chamamos this.app.singleton
.
Finalmente, precisamos registrar este provedor como qualquer outro provedor dentro do arquivo start/app.js
:
// .start/app.js
const providers = [
path.join(__dirname, '..', 'providers', 'Queue/Provider')
]
Agora, podemos chamar use('Bee/Queue')
dentro de qualquer arquivo em seu aplicativo para usá-lo:
const Queue = use('Bee/Queue')
Queue
.get('addition')
.createJob({ x: 2, y: 3 })
.save()
Distribuindo como um pacote
O provedor bee queue que criamos reside na mesma estrutura do projeto. No entanto, podemos extraí-lo em seu próprio pacote.
Vamos criar um novo diretório com a seguinte estrutura de diretório:
└── providers
└── QueueProvider.js
├── src
└── Queue
└── index.js
└── package.json
Tudo o que fizemos foi mover a implementação real de Queue
para o diretório src
e renomear o arquivo do provedor para QueueProvider.js
.
Além disso, temos que fazer as seguintes alterações:
- Como
Queue/index.js
está em um diretório diferente, precisamos ajustar a referência a esse arquivo dentro do nosso provedor de serviços. - Renomeie o namespace
Bee/Queue
para um namespace mais adequado, que tenha menos chances de colisão. Por exemplo, ao criar este provedor para AdonisJs, o nomearemos comoAdonis/Addons/Queue
.
// .providers/QueueProvider.js
const { ServiceProvider } = require('@adonisjs/fold')
class QueueProvider extends ServiceProvider {
register () {
this.app.singleton('Adonis/Addons/Queue', () => {
const Config = this.app.use('Adonis/Src/Config')
return new (require('../src/Queue'))(Config)
})
}
}
module.exports = QueueProvider
OBSERVAÇÃO
Não inclua @adonisjs/fold
como uma dependência para seu provedor, pois ele deve ser instalado apenas pelo aplicativo principal. Para testes, você pode instalá-lo como uma dependência dev.
Escrevendo testes de provedor
O AdonisJs usa oficialmente japa para escrever testes de provedor, embora você possa usar qualquer mecanismo de teste que desejar.
Configurar o japa é simples:
npm i --save-dev japa
Crie os testes dentro do diretório test
:
mkdir test
Os testes podem ser executados executando o arquivo de teste usando o comando node
:
node test/example.spec.js
Para executar todos os seus testes juntos, você pode usar japa-cli
:
npm i --save-dev japa-cli
E executar todos os testes via:
./node_modules/.bin/japa
FAQ's
Por que não instalar @adonisjs/fold
como uma dependência?
Este requisito é para que a versão principal do aplicativo @adonisjs/fold
esteja sempre instalada para seu provedor usar. Caso contrário, cada provedor acabará enviando sua própria versão do contêiner AdonisJS IoC. Se você já trabalhou com o gulp, eles também recomendam (p:14) não instalar o gulp como uma dependência ao criar plugins.