返回
在 TypeScript 服务中传递参数的最佳实践:构造函数还是执行时?
javascript
2024-03-19 11:45:40
在 TypeScript 服务中使用构造函数参数和执行参数的最佳实践
概述
在 TypeScript 中构建服务时,面临的一个常见问题是如何在服务的构造函数中传递参数,以及何时在服务执行时传递参数。对于这个问题,最佳实践取决于服务的设计和目标。
构造函数参数
在以下情况下,建议将参数传递给服务的构造函数:
- 传递必需的依赖项: 当服务需要在构造时初始化依赖项时,将这些依赖项作为构造函数参数传递非常重要。这确保了服务在创建时拥有正确配置。
- 不可变状态: 如果服务的状态不可变(即随着时间的推移保持不变),则将初始状态作为构造函数参数传递是有意义的。这有助于确保服务的实例始终处于已知状态。
- 优化性能: 在某些情况下,将数据作为构造函数参数传递可以优化性能。例如,如果服务需要在构造时对大数据集进行处理,则将数据集作为构造函数参数传递可以避免在每个执行调用中重新处理。
执行参数
在以下情况下,建议在服务执行时传递参数:
- 动态数据: 当服务需要在执行时处理动态数据时,将数据作为执行参数传递是合适的。这允许服务根据传入的数据调整其行为。
- 可变状态: 如果服务的状态可变(即随着时间的推移而改变),则将操作数据作为执行参数传递更有意义。这允许服务在不影响其内部状态的情况下修改传入的数据。
- 灵活性: 使用执行参数提供灵活性,允许服务根据特定调用进行不同的操作。
实际示例
为了更好地理解概念,让我们考虑一个过滤行服务的实际示例:
class FilterRowsService {
// 依赖注入
constructor(private rows: AvailablesLogWithDate[]) {}
// 执行时参数
execute({
dates,
descriptions,
products,
warehouse,
}: {
dates?: Dates;
descriptions?: string[];
products?: string[];
warehouse?: string;
} = {}): AvailablesLogWithDate[] {
// 使用执行参数过滤行
let filteredRows = rows;
if (dates) {
filteredRows = this.filterByDates(dates, filteredRows);
}
if (descriptions) {
filteredRows = this.filterByDescriptions(descriptions, filteredRows);
}
if (products) {
filteredRows = this.filterByProducts(products, filteredRows);
}
if (warehouse) {
filteredRows = this.filterByWarehouse(warehouse, filteredRows);
}
return filteredRows;
}
// 私有过滤方法
private filterByDates(dates: Dates, rows: AvailablesLogWithDate[]): AvailablesLogWithDate[] {
// ...过滤逻辑
}
// ...其他私有过滤方法
}
在这个示例中,行作为构造函数参数传递,因为它们是必需的依赖项。执行时参数用于过滤行,因为这些参数是动态的,可能根据调用而变化。
结论
在 TypeScript 服务中何时传递参数是一个权衡。考虑服务的依赖项、状态可变性、性能和灵活性需求,以确定最佳方法。
常见问题解答
-
为什么不能始终在构造函数中传递参数?
- 有时,参数是动态的,在构造时无法知道。执行参数允许服务根据每个调用进行调整。
-
构造函数参数和执行参数是否可以同时使用?
- 是的,可以同时使用它们。构造函数参数用于传递必需的依赖项和不可变状态,而执行参数用于传递动态数据和可变状态。
-
如果我需要在构造函数中传递大量数据,该怎么办?
- 考虑使用依赖注入框架,例如 NestJS 或 Angular Injectable,它允许在构造函数中轻松注入依赖项。
-
何时应该传递服务作为构造函数参数?
- 当服务被多个其他服务使用时,并且需要在所有服务实例中共享其状态时。
-
执行参数是否应该始终是可选的?
- 这取决于服务的设计。如果参数对于服务的正常功能是必需的,则可以使其成为必填项。