跳到主要内容

get

根据 ID 获取实体。

方法签名

get(id: EntityIdType): Observable<InstanceType<T>>

示例

基础用法

import { firstValueFrom } from 'rxjs';

const todo = await firstValueFrom(Todo.get('591e97aa-f7e3-499c-9fa4-4e2ae4459ef6'));
console.log(todo.title);

响应式订阅

const subscription = Todo.get(todoId).subscribe(todo => {
console.log(todo.title);
});

subscription.unsubscribe();

批量获取

// 批量获取多个实体
const todoIds = ['id-1', 'id-2', 'id-3'];

const todos = await Promise.all(todoIds.map(id => firstValueFrom(Todo.get(id))));

结合错误处理

import { catchError, of } from 'rxjs';

const todo$ = Todo.get(todoId).pipe(
catchError(error => {
console.error('获取 todo 失败:', error);
return of(null);
})
);

get vs findOne

方法查询方式性能参数返回值
get主键索引最快仅需要 IDObservable<T>
findOne条件查询较慢复杂查询条件Observable<T | undefined>
// get - 适合已知 ID 的情况
const todo1 = await firstValueFrom(Todo.get('todo-id'));

// findOne - 适合需要条件查询的情况
const todo2 = await firstValueFrom(
Todo.findOne({
where: {
combinator: 'and',
rules: [
{ field: 'userId', operator: '=', value: 'user-123' },
{ field: 'completed', operator: '=', value: false }
]
}
})
);

性能优化

1. 使用 get 而非 findOne

当你已经知道实体的 ID 时,始终优先使用 get 而不是 findOne

// ✅ 好:直接通过 ID 获取
Todo.get(todoId);

// ❌ 不必要的复杂:使用 findOne 查询 ID
Todo.findOne({
where: {
combinator: 'and',
rules: [{ field: 'id', operator: '=', value: todoId }]
}
});

2. 缓存策略

实体获取后会被缓存,重复调用 get 时会直接返回缓存的实体引用:

// 第一次调用会从数据库读取
const todo1 = await firstValueFrom(Todo.get(todoId));

// 第二次调用会返回相同的实体引用
const todo2 = await firstValueFrom(Todo.get(todoId));

console.log(todo1 === todo2); // true - 相同的对象引用

3. 响应式更新

使用 Observable 订阅,当实体更新时自动收到通知:

const subscription = Todo.get(todoId).subscribe(todo => {
console.log('Todo 更新了:', todo);
});

// 在其他地方更新这个 todo
await Todo.update(todo, { completed: true });
// 上面的订阅会自动收到更新后的 todo

错误处理

ID 不存在时的处理

import { catchError, EMPTY } from 'rxjs';

// 方式 1: 使用 catchError 捕获错误
const todo$ = Todo.get(todoId).pipe(
catchError(error => {
if (error.code === 'ENTITY_NOT_FOUND') {
console.log('Todo 不存在');
return EMPTY;
}
throw error;
})
);

// 方式 2: 使用 try-catch
try {
const todo = await firstValueFrom(Todo.get(todoId));
} catch (error) {
console.error('获取失败:', error);
}

常见用例

1. 路由参数获取实体

import { ActivatedRoute } from '@angular/router';
import { switchMap } from 'rxjs';

@Component({
selector: 'app-todo-detail'
})
export class TodoDetailComponent {
todo$ = this.route.params.pipe(switchMap(params => Todo.get(params['id'])));

constructor(private route: ActivatedRoute) {}
}

2. 实时数据同步

// 订阅实体变化,实现实时更新
const todoSubscription = Todo.get(todoId).subscribe(todo => {
// 每当这个 todo 在数据库中被更新时
// 这里会自动收到最新的数据
updateUI(todo);
});

3. 预加载相关数据

// 获取 todo 并预加载相关的用户信息
const todoWithUser$ = Todo.get(todoId).pipe(
switchMap(todo => User.get(todo.userId).pipe(map(user => ({ todo, user }))))
);

最佳实践

  1. 优先使用 get:当有 ID 时,始终使用 get 而不是 findOne
  2. 利用缓存:理解实体缓存机制,避免不必要的重复查询
  3. 响应式编程:使用 Observable 订阅而非 Promise,享受自动更新的好处
  4. 错误处理:始终处理实体不存在的情况
  5. 类型安全:利用 TypeScript 类型推断,避免类型错误

参考

  • findOne - 根据条件查找单个实体
  • findOneOrFail - 查找单个实体,找不到抛出错误
  • find - 查询多个实体