配置提供者
一些配置文件如 (config/hash.ts) 不会将配置导出为普通对象。相反,它们导出一个配置提供者。配置提供者为包提供了一个透明的 API,以便在应用程序启动后延迟计算配置。
不使用配置提供者
为了理解配置提供者,让我们看看如果我们不使用配置提供者,config/hash.ts 文件会是什么样子。
import { Scrypt } from '@adonisjs/core/hash/drivers/scrypt'
export default {
default: 'scrypt',
list: {
scrypt: () => new Scrypt({
cost: 16384,
blockSize: 8,
parallelization: 1,
maxMemory: 33554432,
})
}
}到目前为止,一切都很好。我们直接导入 scrypt 驱动程序并使用工厂函数返回一个实例,而不是从 drivers 集合中引用它。
假设 Scrypt 驱动程序需要 Emitter 类的实例,以便每次哈希值时发出事件。
import { Scrypt } from '@adonisjs/core/hash/drivers/scrypt'
import emitter from '@adonisjs/core/services/emitter'
export default {
default: 'scrypt',
list: {
scrypt: () => new Scrypt({
cost: 16384,
blockSize: 8,
parallelization: 1,
maxMemory: 33554432,
}, emitter)
}
}🚨 上面的例子会失败,因为 AdonisJS 容器服务在应用程序启动之前不可用,而配置文件在应用程序启动阶段之前就被导入了。
好吧,这是 AdonisJS 架构的问题 🤷🏻♂️
不是的。让我们不使用容器服务,直接在配置文件中创建 Emitter 类的实例。
import { Scrypt } from '@adonisjs/core/hash/drivers/scrypt'
import { Emitter } from '@adonisjs/core/events'
const emitter = new Emitter()
export default {
default: 'scrypt',
list: {
scrypt: () => new Scrypt({
cost: 16384,
blockSize: 8,
parallelization: 1,
maxMemory: 33554432,
}, emitter)
}
}现在,我们有一个新问题。我们为 Scrypt 驱动程序创建的 emitter 实例不是全局可用的,我们无法导入它并监听驱动程序发出的事件。
因此,你可能想将 Emitter 类的构造移动到它自己的文件中并导出它的实例。这样,你可以将 emitter 实例传递给驱动程序并用它来监听事件。
// title: start/emitter.ts
import { Emitter } from '@adonisjs/core/events'
export const emitter = new Emitter()import { Scrypt } from '@adonisjs/core/hash/drivers/scrypt'
import { emitter } from '#start/emitter'
export default {
default: 'scrypt',
list: {
scrypt: () => new Scrypt({
cost: 16384,
blockSize: 8,
parallelization: 1,
maxMemory: 33554432,
}, emitter)
}
}上面的代码可以正常工作。但是,这次你是手动构造应用程序需要的依赖项。因此,你的应用程序将有大量样板代码来将所有内容连接在一起。
使用 AdonisJS,我们努力编写最少的样板代码,并使用 IoC 容器进行依赖项查找。
使用配置提供者
现在,让我们重写 config/hash.ts 文件,这次使用配置提供者。配置提供者是一个接受 Application 类实例并使用容器解析其依赖项的函数的花哨名称。
import { configProvider } from '@adonisjs/core'
import { Scrypt } from '@adonisjs/core/hash/drivers/scrypt'
export default {
default: 'scrypt',
list: {
scrypt: configProvider.create(async (app) => {
const emitter = await app.container.make('emitter')
return () => new Scrypt({
cost: 16384,
blockSize: 8,
parallelization: 1,
maxMemory: 33554432,
}, emitter)
})
}
}一旦你使用 hash 服务,scrypt 驱动程序的配置提供者将被执行以解析其依赖项。因此,我们在代码的其他地方使用 hash 服务之前不会尝试查找 emitter。
由于配置提供者是异步的,你可能想通过动态导入延迟导入 Scrypt 驱动程序。
import { configProvider } from '@adonisjs/core'
export default {
default: 'scrypt',
list: {
scrypt: configProvider.create(async (app) => {
const { Scrypt } = await import('@adonisjs/core/hash/drivers/scrypt')
const emitter = await app.container.make('emitter')
return () => new Scrypt({
cost: 16384,
blockSize: 8,
parallelization: 1,
maxMemory: 33554432,
}, emitter)
})
}
}如何访问已解析的配置?
你可以直接从服务访问已解析的配置。例如,对于 hash 服务,你可以按如下方式获取已解析配置的引用。
import hash from '@adonisjs/core/services/hash'
console.log(hash.config)