Service Provider
adonisJS 要实现 Controller 和 Service 的分离,这里用到 Service Provider。
-
将 Provider 注入到 adonis 中
bash1touch providers/ServiceProvider.ts在配置文件
.adonisrc.json中注入这个 Provider。js1 "providers": [ 2 "./providers/ServiceProvider", 3 ... 4 ] -
创建一个接口并用一个 class implement 它,这个 class 里写 service 代码
bash1touch Service/Login.tsjs1export interface Login_Interface { 2 signup: () => Promise<any>; 3} 4 5export default class Login implements Login_Interface { 6 public database; 7 constructor(database: typeof Database) { 8 this.database = database; 9 } 10 public async signup() { 11 ... 12 } 13}注意:由于注入的 Service 的实例方法中不能直接使用
import Database from @ioc:Adonis/Lucid/Database,所以这里在 constructor 时传递 database 过去。 -
在 ServiceProvider 中注册 Service
js1import { ApplicationContract } from "@ioc:Adonis/Core/Application"; 2import Login from "../Service/Login"; 3 4export default class ServiceProvider { 5 constructor(protected app: ApplicationContract) {} 6 public register() { 7 this.app.container.singleton("Loc/Signup", () => { 8 const database = this.app.container.use("Adonis/Lucid/Database"); 9 return new Login(database); 10 }); 11 } 12 public async boot() { 13 // IoC container is ready 14 } 15 16 public async ready() { 17 // App is ready 18 } 19 20 public async shutdown() { 21 // Cleanup, since app is going down 22 } 23}这个 Provider 的注册周期内,用单例模式注册一个 Login 实例。
由于 Provider 中也不能直接引入
Database,所以这里使用this.app.container.use("Adonis/Lucid/Database")将 database 对象传递过去,这里就接上了第一步中的constructor。 -
暴露出这个实例的方法
bash1touch contracts/login.tsjs1declare module "@ioc:Loc/Signup" { 2 import { Login_Interface } from "Service/Login"; 3 const login: Login_Interface; 4 export default login; 5}这样在 Typescript 下,就会有语法提示。
-
Controller 中调用 Service 的代码
js1import loginInstance from "@ioc:Loc/Signup"; 2 3export default class LoginController { 4 public async signup() { 5 return loginInstance.signup(); 6 } 7 ... 8} -
补充 service 方法,这里的示例是调用数据库查询
js1 public async signup() { 2 const { default: Users } = await import("App/Models/User"); 3 const dbRes = await this.database.from("users").where("user", "邱彦兮"); 4 const ormRes = await Users.query().select("*").where("user", "邱彦兮"); 5 console.log("🚀🚀🚀🚀🚀 - res:", [...dbRes, ...ormRes]); 6 return [...dbRes, ...ormRes]; 7 }在 service 中,不管是用 database 还是 orm 都不能直接
import xxx from xxx。这里的细节在于:
- 取
constructor后的 database 对象来查询数据库 - 使用
await import("App/Models/User")获取 orm 版本的数据库查询对象来查询数据库
- 取
现在你已经实现了 Controller 和 Service 的分离。