前面我们了解过怎么把依赖绑定到 IoC 容器里,下面继续往后看看关于 Service Providers 的东西,了解怎么发行与 Adonis 生态系统相兼容的包。
介绍
ioc.bind 方法可以用来注册绑定,不过现在还没有明确的说明要在哪里调用这个方法。这就是 Service Providers 做的事情。Service Providers 就是简单的类,里面带着一些生命周期方法可以用来注册与启动绑定。
const { ServiceProvider } = require('@adonisjs/fold') class MyProvider extends ServiceProvider { register () { // register bindings } boot () { // optionally do some initial setup } } module.exports = MyProvider
Provider 类里的 register 方法是用来注册绑定的,在这个方法里你不能使用其它的绑定。boot 方法会在所有的 providers 都已经注册了以后被调用。这时候可以使用已有的绑定去做一些初始化的操作。
比如,添加一个 View global:
boot () { const View = this.app.use('Adonis/Src/View') View.global('time', () => new Date().getTime()) }
Npm 包作为 Service Provider
下面了解一下怎么把已有的 npm 包变成一个 Service Provider。应用里的 Provider 存储在应用根目录下的 providers 这个目录里面。
目录结构
├── app └── providers └── Queue └── index.js └── Provider.js └── start
原则
比如我们要把 bee-queue 注册成一个 Provider。下面是一些遵循的原则。
- 用户不需要配置 queue provider。
- 所有的配置放在 config/queue.js 文件里。
- 使用不同配置创建新的 queue 要非常简单。
实施
providers/Queue/index.js:
'use strict' const BeeQueue = require('bee-queue') class Queue { constructor (Config) { this.Config = Config this._queuePool = {} } get (name) { /** * If there is an instance of queue already, then return it */ if (this._queuesPool[name]) { return this._queuesPool[name] } /** * Read configuration using Config * provider */ const config = this.Config.get(`queue.${name}`) /** * Create a new queue instance and save it's * reference */ this._queuesPool[name] = new BeeQueue(name, config) /** * Return the instance back */ return this._queuesPool[name] } } module.exports = Queue
上面这类里面只有一个 get 方法,它会返回指定名字的 queue 实例。下面是 get 方法做的事情:
- 查找指定名字的 queue 实例。
- 如果实例不存在,在 Config provider 那里读取相关配置。
- 创建新的 bee-queue 实例存储在一个对象里。
- 返回实例。
Queue 保持了纯洁性,因为它不强依赖框架里的东西,它需要的 Config ,会用依赖注入(Dependency Injection)的方式提供。
Service provider
现在可以去创建一个 Service provider,用它实例化上面的类并且把它绑定在 Ioc 容器里。下面代码在 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
this.app 指的就是 ioc 对象,所以我们可以使用 this.app.singleton 代替 ioc.singleton 。
最后,我们需要在 start/app.js 文件里注册 Provider :
const providers = [ path.json(__dirname, '..', 'providers', 'Queue/provider') ]
现在,我们就可以在应用的任何文件里使用 use('Bee/Queue') :
const Queue = use('Bee/Queue') Queue .get('addition') .createJob({ x:2, y:3 }) .save()
发行包
把之前创建的 bee queue provider 做成自己的包。创建一个目录结构:
└── providers └── QueueProvider.js ├── src └── Queue └── index.js └── package.json
主要就是把实施的 Queue 放在了 src 目录的下面,名字改成了 QueueProvider.js 。
另外还需要做下面这些修改:
- 因为 Queue/index.js 在不同的目录里了,所以得在 Service provider 里面修改这个文件的引用。
- 重命名 Bee/Queue,比如 Adonis/Addons/Queue。
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 = QueueProviderNode.js
评论
这个博客的质量真的太高了,宁皓网就是个宝藏
6 年 7 个月 以前
谢谢啊。嘿嘿。
6 年 7 个月 以前