MST

星途 面试题库

面试题:TypeScript装饰器与依赖注入在异步场景下的深度实践

考虑一个高并发的Web应用场景,其中服务之间存在异步依赖关系,例如一个`ProductService`依赖于`InventoryService`和`ShippingService`,且这两个服务的调用都是异步的。使用TypeScript装饰器和依赖注入,设计一个健壮的解决方案,确保在异步调用过程中依赖的正确注入和管理,处理可能出现的并发问题,如竞争条件,并阐述如何利用装饰器实现异步中间件的功能,给出完整且可运行的代码示例以及详细的设计思路。
16.3万 热度难度
前端开发TypeScript

知识考点

AI 面试

面试题答案

一键面试

设计思路

  1. 依赖注入:使用TypeScript装饰器实现依赖注入,通过装饰器将InventoryServiceShippingService注入到ProductService中。
  2. 异步处理:由于InventoryServiceShippingService的调用是异步的,使用async/await来处理异步操作,确保代码的可读性和顺序性。
  3. 竞争条件处理:利用Promise.all来并行执行异步操作,避免竞争条件。同时,可以使用锁机制或队列来进一步处理复杂的并发情况。
  4. 异步中间件:通过装饰器实现异步中间件功能,在服务调用前后执行一些通用的逻辑,如日志记录、性能监控等。

代码示例

// 定义服务接口
interface InventoryService {
  checkInventory(productId: string): Promise<boolean>;
}

interface ShippingService {
  calculateShipping(productId: string): Promise<number>;
}

// 实现服务
class DefaultInventoryService implements InventoryService {
  async checkInventory(productId: string): Promise<boolean> {
    // 模拟异步操作
    await new Promise(resolve => setTimeout(resolve, 1000));
    return true;
  }
}

class DefaultShippingService implements ShippingService {
  async calculateShipping(productId: string): Promise<number> {
    // 模拟异步操作
    await new Promise(resolve => setTimeout(resolve, 1000));
    return 10;
  }
}

// 依赖注入装饰器
function inject<T>(service: T) {
  return function (target: any, propertyKey: string) {
    target[propertyKey] = service;
  };
}

// 异步中间件装饰器
function asyncMiddleware(middleware: (target: any, ...args: any[]) => Promise<void>) {
  return function (target: any, propertyKey: string, descriptor: PropertyDescriptor) {
    const originalMethod = descriptor.value;
    descriptor.value = async function (...args: any[]) {
      await middleware(this, ...args);
      return originalMethod.apply(this, args);
    };
    return descriptor;
  };
}

// 产品服务
class ProductService {
  @inject(new DefaultInventoryService())
  private inventoryService: InventoryService;

  @inject(new DefaultShippingService())
  private shippingService: ShippingService;

  @asyncMiddleware(async function (this: ProductService, productId: string) {
    console.log(`Starting processing for product ${productId}`);
  })
  async processProduct(productId: string) {
    const [hasInventory, shippingCost] = await Promise.all([
      this.inventoryService.checkInventory(productId),
      this.shippingService.calculateShipping(productId)
    ]);
    if (hasInventory) {
      console.log(`Product ${productId} is available. Shipping cost: ${shippingCost}`);
    } else {
      console.log(`Product ${productId} is out of stock.`);
    }
  }
}

// 测试
const productService = new ProductService();
productService.processProduct('12345');

代码解释

  1. 服务接口和实现:定义了InventoryServiceShippingService接口及其实现类,模拟了异步操作。
  2. 依赖注入装饰器inject装饰器将服务实例注入到ProductService的属性中。
  3. 异步中间件装饰器asyncMiddleware装饰器在processProduct方法调用前后执行中间件逻辑。
  4. 产品服务ProductService类使用依赖注入装饰器注入InventoryServiceShippingService,并使用asyncMiddleware装饰器添加异步中间件。processProduct方法使用Promise.all并行执行异步操作,并处理结果。
  5. 测试:创建ProductService实例并调用processProduct方法,观察输出结果。