问题描述
我将向您展示我正在尝试做的事的一个例子:
server.ts
export class ExpressServer {
public readonly app: express.Application;
public readonly lbApp: ImportedApp;
private server?: Server;
constructor(options: ApplicationConfig = {}) {
this.app = express();
this.lbApp = new ImportedApp(options);
this.app.get('/hello',async function (_req: Request,res: Response) {
//Here i'd like to call a model like User.findById() but can't figure out how to do it..
});
}
}
正如您在评论中看到的那样,我正在尝试访问我的模型方法以在路线中使用它们(就像在视图中显示用户信息一样),但无法弄清楚该怎么做。我已经尝试导入数据源,模型,控制器,但是什么都不包含我的方法(FindById,创建等)。
如果我什么也没找到,我将不得不使用Axios
或Request
之类的东西来从api请求资源,而不是在我的代码中之类的await request('api/users/myusername)
解决方法
在LoopBack 4中,我们使用存储库设计模式来访问数据。为了通过其ID查找用户实例,您需要通过依赖注入获得UserRepository
的实例。引用https://loopback.io/doc/en/lb4/Repository.html:
存储库正在向模型添加行为。模型描述数据的形状,存储库提供类似于CRUD操作的行为。这与LoopBack 3.x(模型也实现行为)不同。
更新的解决方案
要获取Repository类的实例,可以使用Service Locator设计模式,并从LoopBack的REST层提供的每个请求Context对象中获取实例。
import {MIDDLEWARE_CONTEXT,RequestContext} from '@loopback/rest';
import {UserRepository} from '../repositories';
function expressHandler(req,res,next) {
const ctx = (req as any)[MIDDLEWARE_CONTEXT];
const userRepo = await ctx.get<UserRepository>('repositories.UserRepository');
const users = await userRepo.find({limit: 10});
// render your view
}
我们正在讨论如何使该用例更易于在GitHub pull request loopback-next#6793中实现,欢迎随时加入讨论。
原始答案
我建议您编写一个LoopBack 4控制器,而不是为呈现的页面编写Express路由。并注入Express Response对象,以允许您呈现HTML视图,如https://loopback.io/doc/en/lb4/Accessing-http-request-response.html#inject-http-response
中所述import {Response,RestBindings,oas} from '@loopback/rest';
import {inject} from '@loopback/core';
import {UserRepository} from '../repositories';
export class PingController {
constructor(
@inject(RestBindings.Http.RESPONSE)
private response: Response
@repository(UserRepository)
public userRepository: UserRepository,) {}
// Hide this endpoint from OpenAPI spec generated for the app
@oas.visibility('undocumented')
@get('/users')
list(): Response {
// Access User data via this.userRepository API
const users = await this.userRepository.find({limit: 10});
// Access the response object via `this.response`
this.response.render('users',{users});
// Return the HTTP response object so that LoopBack framework skips the
// generation of HTTP response
return this.response;
}
}
话虽如此,如果您已经知道如何在Express路由中从LB4应用访问数据源实例,那么您也可以从路由中手动实例化存储库类:
const db = // your datasource
this.app.get('/hello',async function (_req: Request,res: Response) {
const repo = new UserRepository(db);
const users = await this.userRepository.find({limit: 10});
});
,
对我来说,解决方案不起作用。从 express-composition 示例开始,我只需要从 lb4 请求处理程序外部的通用快速路由访问 lb 存储库:
constructor(options: ApplicationConfig = {}) {
this.app = express();
this.lbApp = new NoteApplication(options);
this.lbApp.basePath('')
// Expose the front-end assets via Express,not as LB4 route
this.app.use('/api',this.lbApp.requestHandler);
this.app.get('/hello',async (req: Request,res: Response) => {
const ctx = (req as any)[MIDDLEWARE_CONTEXT];
const userRepo = await ctx.get('repositories.UserRepository');
res.send('Hello world!');
});
}
行中的ctx
const ctx = (req as any)[MIDDLEWARE_CONTEXT];
总是未定义的。
我的主要目标是让路由不在 /api 下仍然可以访问 lb4 存储库。