快速路由内的访问模型方法(环回 4)

Access model method inside express route (Loopback 4)

我将向您展示我正在尝试做的事情的示例:

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、Create 等)

如果我什么也没找到,我将不得不使用 AxiosRequest 之类的东西从 api 请求资源,而不是在我的代码中使用 await request('api/users/myusername)

在 LoopBack 4 中,我们使用 Repository 设计模式来访问数据。为了通过 id 找到用户实例,您需要通过依赖注入获取 UserRepository 的实例。引用自 https://loopback.io/doc/en/lb4/Repository.html:

Repositories are adding behavior to Models. Models describe the shape of data, Repositories provide behavior like CRUD operations. This is different from LoopBack 3.x where models implement behavior too.

更新的解决方案

要获取存储库实例 class,您可以使用服务定位器设计模式并从 LoopBack 的 REST 层提供的每个请求上下文对象中获取实例。

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 拉取请求 loopback-next#6793 中讨论如何使这个用例更容易实现,欢迎加入那里的讨论。

原始答案

与其为呈现的页面编写 Express 路由,我建议您改为编写 LoopBack 4 Controller;并注入 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 应用程序访问 DataSource 实例,那么您也可以从您的路由中手动实例化 Repository classes:

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 请求处理程序的通用快速路由 outside 访问 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 存储库。