# awilix
- awilix 依赖注入 DI(Dependency Injection)【神之浩劫的近战刺客】
- DI 的作用是减少程序模块之间的耦合程度,提高代码的可可维护性
- DI 容器的功能是将系统中的模块整合起来,从而让开发者不在需要太关注这些 DI 的实现细节问题。
- awilix 的实现是基于 ES6Proxies
# 用例 01
// configureContainer.js
import { createContainer, asClass, asFunction } from "awilix";
import makeTodosService from "./todosService";
import TodosRepository from "./todosRepository";
export default function configureContainer(){
// 注册一个容器
const container = createContainer();
container.register({
todosService: asFunction(makeTodosService).scoped(); // scoped() 每一个作用域都是一个实例
todosRepository: asClass(TodosRepository).singliton();
})
return container;
}
// app.js
import Koa from "koa";
import KoaRouter from "koa-router";
import {asValue} from "awilix";
import {scopePerRequest, makeInvoker} from "awilix-koa";
import configureContainer from "./configureContainer";
const app = new Koa();
const router = new KoaRouter();
const container = configureContainer();
app.use(scopePerRequest(container))
app.use((ctx, next)=>{
ctx.state.container.register(Value)({
currentUser: ctx.state.user
})
return next();
})
const todosAPI = ({ todosService } => {
return {
getTodos: async (ctx) => {
const todos = await todosService.getTodos(ctx.request.query)
ctx.body = todos
ctx.status = 200
},
createTodos: async (ctx) => {
const todo = await todosService.createTodo(ctx.request.body)
ctx.body = todo
ctx.status = 201
},
updateTodo: async (ctx) => {
const updated = await todosService.updateTodo(
ctx.params.id,
ctx.request.body
)
ctx.body = updated,
ctx.status = 200
},
deleteTodo: async (ctx) => {
await todosService.deleteTodo(
ctx.params.id,
ctx.request.body
)
}
}
})
const api = makeInvoker(todosAPI);
router.get('/todos', api('getTodos'))
router.post('/todos', api('createTodos'))
router.patch('/todos/:id', api('updateTodo'))
router.patch('/todos/:id', api('deleteTodo'))
app.use(router.routes())
app.listen(1337)
# 用例 02
引用项目地址[https://github.com/Wlwulan/wulan/tree/943f2d48d9cd44dbfae5f1e97c0c4e9489d60209/six/yd-books-back]
import Koa from "koa";
import serve from "koa-static";
import config from "./config";
import render from "koa-swig";
import co from "co";
import log4js from "log4js";
import errorHandle from "./middlewares/errorHandler";
import { Lifetime, createContainer } from "awilix";
import { scopePerRequest, loadControllers } from "awilix-koa";
const app = new Koa();
const container = createContainer(); // 创建一个容器,管理所有服务的路由
// 把所有的service注册容器
// 每一个controller把需要的service注册进去
container.loadModules([__dirname + "/services/*.js"], {
formatName: "camelCase",
registerOptions: {
lifetime: Lifetime.SCOPED, // Lifetime.
},
});
/**
* 配置特定的全局生存周期
* container.loadModules([
* ["services/*.js", Lifetime.SCOPED],
* "repositories/*.js",
* "db/db.js"
* ], {
* resolverOptions: {
* lifetime: Lifetime.SINGLETON
* }
* })
*/
app.use(scopePerRequest(container));
// 前端模板
app.context.render = co.wrap(
render({
root: config.viewDir,
autoescape: true,
// cache: "memory", // 模板缓存
varControls: ["[[", "]]"],
ext: "html",
writeBody: false,
})
);
log4js.configure({
appenders: {
cheese: {
type: "dateFile",
filename: __dirname + "/logs/log.log",
pattern: "-yyyy-MM-dd",
backups: 10,
},
},
categories: {
default: {
appenders: ["cheese"],
level: "error",
},
},
});
const logger = log4js.getLogger("cheese");
errorHandle.error(app, logger);
// 自动注册路由
app.use(loadControllers(__dirname + "/controllers/*.js"), {
cwd: __dirname,
});
// 配置静态资源
app.use(serve(config.staticDir));
app.listen(config.port, () => {
console.log("服务已启动");
});
// 在路由中使用
// /controllers/
import {router, GET} from "awilix-koa";
// cheerio jquery的核心功能的简洁实现,主要是为了用在服务器需要对DOM进行操作的地方
const cheerio = require("cheerio");
@route("/books");
class BooksController{
constructor({bookService}){
this.bookService= bookService;
}
@route("/index")
@GET()
async actionIndex(ctx, next){
const result = await this.bookService.getData();
// console.log(result)
const html = await ctx.render("books/pages/index", {
data: result.data
});
if(ctx.request.header["x-pjax"]){
const $ = cheerio.load(html);
ctx.body = $("#js-hooks-data").html();
} else {
ctx.body = html
}
}
@route("/create")
@GET()
actionCreate(){
return async(ctx, next){
const html = await ctx.render("books/pages/add");
if(ctx.request.header["x-pjax"]){
const $ = cheerio.load(html);
let _result = "";
$(".pjaxcontent").each(function(){
_result += $(this).html();
});
$(".lazyload-css").each(function(){
_result +=$(this).html();
});
$(".lazyload-js").each(function(){
_result = `<script>${$(this).attr("src")}</script>`;
});
ctx.body = _result;
} else {
ctx.body = html
}
}
}
@route("/savedata")
@GET()
actionSaveData(){
return async (ctx, next)=>{
// web api 提供的一个方法,用于定义一些实用方法来处理URL的查询字符串
const params = new URLSearchParams();
params.append("Books[title]", "书名");
params.append("Books[author]", "作者");
params.append("Books[publisher]", "出版社");
const result = await this.bookService.saveData({
params
});
ctx.body = result;
}
}
}
module.exports = BookController;
// services/BookService
/** jsdoc文档生成的写法 */
const SafeRequest = require("../utils/SafeRequest");
class Book{
constructor(app){}
/**
* 获取后台的全部图书数据方法
* @param {*} options 配置项
* @example
* retrun new Promise
* getData(options)
*/
getData(options){
const safeRequest = new SafeRequest("books/index");
return safeRequest.fetch({});
}
/**
* 创建图书索引
* @param {*} options 配置项
* @example
* retrun new Promise
* saveData(options)
*/
saveData(options){
const safeRequest = new SafeRequest("books/create");
return safeRequest.fetch({
method: "POST",
params: options.params
});
}
}
module.exports = Book;
← MySQL 常用 SQL 语句大全 co →