首页 > 解决方案 > 对几个 URL 端点使用一个请求 - 角度

问题描述

我将解释,我正在尝试将 getProducts(后端控制器)用于网站中的 3 个页面,这些页面使用解析器来显示数据,以下是选项 -

http://localhost:4200/product-list?gender=2&category=4

http://localhost:4200/product-list?gender=2

http://localhost:4200/product-list?category=4

我可以使用相同的控制器吗?我想我可以,但我不知道怎么做。

前端代码 -

html示例-

只有性别——

   <a
    class="navLink navLink--gender"
    click="refreshPage()"
    [routerLink]="['/product-list']"
    [queryParams]="{ category: 1 }">
    Men
  </a>

性别和类别 -

       <a
        class="linkCategoriesInner__link"
        click="refreshPage()"
        [routerLink]="['/product-list']"
        [queryParams]="{ gender: 1, category: 1 }">
        Jeans
      </a>

路由模块 -

 {
    path: 'product-list',
    component: ProductsComponent,
    resolve: { users: ProductsResolver },
  }

产品列表组件 -

constructor(private route: ActivatedRoute) { 
     this.refreshPage();
  }

  public refreshPage() {
      this.route.data.subscribe((data: Data) => {
      const products = data['users'] as IProductInterface[];

      if (products.length === 0) {
        this._noProducts = true;
        return;
      }

      this._noProducts = false;

      this._products = products.map((product) => new Product(product));
    });
  }

产品列表解析器 -

class ProductsResolver implements Resolve<Pick<IProductInterface, 'image' | 'title' | 'price' | 'description'>[]> {

  constructor(private productService: ProductService) {}

  resolve(route: ActivatedRouteSnapshot, state: RouterStateSnapshot): Observable<Pick<
  IProductInterface, 'image' | 'title' | 'price' | 'description'>[]> {
    return this.productService.getProducts(
      +route.queryParamMap.get('gender')! as ProductGender,
      +route.queryParamMap.get('category')! as ProductCategory,
    );
  }
}

产品列表服务 -

  public getProducts(
    gender?: ProductGender,
    category?: ProductCategory
  ): Observable<IProductInterface[]> {
    return this.httpProductService.getProducts(gender, category).pipe(
      catchError((errorResponse: HttpErrorResponse) => {
        let errorMessage: string;

        switch (errorResponse.status) {
          case 400:
            errorMessage = 'Getting products failed';
            break;
          default:
            errorMessage = 'An error occurred';
        }

        return throwError(errorMessage);
      }),
      map((response: IGetProductsResponse) => response.data!)
    );
  }

产品列表 http 服务 -

 public getProducts(
    gender?: ProductGender,
    category?: ProductCategory
  ): Observable<IGetProductsResponse> {
    const baseUrl = ENDPOINT;
    
    return this.http.get<IGetProductsResponse>(
      `${baseUrl + 'list/' + gender}/${category}`
    );
  }

上面提到IGetProductsResponse-

export interface IGetProductsResponse extends IResponse {
  readonly data?: IProductInterface[];
}

后端代码 -

路由器——

router.get("/list/:gender/:category", getProducts);

控制器 -

const getProducts = async (
  req: IgetProductsRequest,
  res: IgetProductsResponse
) => {
  ServerGlobal.getInstance().logger.info(
    `<getProducts>: Start processing request filtered by \
category ${req.params.category} and gender ${req.params.gender}`
  );

  if (!ServerGlobal.getInstance().isValidCategoryValue(+req.params.category!)) {
    ServerGlobal.getInstance().logger.error(
      `<getProducts>: Failed to get products because of invalid category filtered by category ${req.params.category} \
and gender ${req.params.gender}`
    );

    res.status(400).send({
      success: false,
      message: "Please provide valid category",
    });
    return;
  }

  if (
    !ServerGlobal.getInstance().isValidGenderValue(+req.params.gender!)
  ) {
    ServerGlobal.getInstance().logger.error(
      `<getProducts>: Failed to get products because of invalid gender filtered by category ${req.params.category} \
 and gender ${req.params.gender}`
    );

    res.status(400).send({
      success: false,
      message: "Please provide valid gender",
    });
    return;
  }

  try {
    const products = await ProductDB.find({
      category: +req.params.category!,
      gender: +req.params.gender!,
    });

    ServerGlobal.getInstance().logger.info(
      `<getProducts>: Successfully got the products filtered by \
category ${req.params.category} and gender ${req.params.gender}`
    );

    res.status(200).send({
      success: true,
      message: "Successfully retrieved products",
      data: products.map((product) => ({
        id: product.id as string,
        category: {
          value: product.category,
          label: ServerGlobal.getInstance().getCategoryLabel(product.category)!,
        },
        gender: {
          value: product.gender,
          label: ServerGlobal.getInstance().getGenderLabel(product.gender)!,
        },
        title: product.title,
        description: product.description,
        price: product.price,
        imageFilename: product.imageFilename,
      })),
    });
    return;
  } catch (e) {
    ServerGlobal.getInstance().logger.error(
      `<getProducts>: Failed to get products filtered by \
category ${req.params.category} and gender ${req.params.gender} because of server error: ${e}`
    );

    res.status(500).send({
      success: false,
      message: "Server error",
    });
    return;
  }
};

上面提到IgetProductsRequest-

interface IgetProductsRequest extends express.Request {
  readonly params: Readonly<{
    gender?: string;
    category?: string;
  }>;
}

上面提到IgetProductsResponse-

type IgetProductsResponse = express.Response<
    IServerResponse & {
        data?: {
            id: string;
            category: { value: ProductCategory, label: string };
            gender: { value: ProductGender, label: string };
            title: string;
            description: string;
            price: number;
            imageFilename: string;
        }[];
    }
>;

标签: htmlnode.jsangulartypescriptexpress

解决方案


您发布了很多代码,下次请提供最少的代码来重现问题。

我更改了控制器以检查性别和/或类别,然后在 ProductDB.find() 函数中使用这些值。

更新的控制器

const getProducts = async (
  req: IgetProductsRequest,
  res: IgetProductsResponse
) => {
  ServerGlobal.getInstance().logger.info(
    `<getProducts>: Start processing request filtered by \
category ${req.params.category} and gender ${req.params.gender}`
  );

  if (!req.params.category && !req.params.gender) {
    res.status(400).send({
      success: false,
      message: "Please provide a category and/or gender",
    });
    return;    
  }

  const dbQueryParams = {};
 
  if (req.params.category) {
    if (!ServerGlobal.getInstance().isValidCategoryValue(+req.params.category!)) {
      ServerGlobal.getInstance().logger.error(`<getProducts>: Failed to get products because \
                                              of invalid category filtered by category ${req.params.category} \
                                              and gender ${req.params.gender}`);

      res.status(400).send({
        success: false,
        message: "Please provide valid category",
      });
      return;
    }
    dbQueryParams.category = +req.params.category!
  }

  if (req.params.gender) {
    if (!ServerGlobal.getInstance().isValidGenderValue(+req.params.gender!) {
      ServerGlobal.getInstance().logger.error(`<getProducts>: Failed to get products because \
                                              of invalid gender filtered by category ${req.params.category} \
                                              and gender ${req.params.gender}`);

      res.status(400).send({
        success: false,
        message: "Please provide valid gender",
      });
      return;
    }
    dbQueryParams.gender = +req.params.gender!
  }


  try {    
    const products = await ProductDB.find(dbQueryParams);

    ServerGlobal.getInstance().logger.info(
      `<getProducts>: Successfully got the products filtered by \
      category ${req.params.category} and gender ${req.params.gender}`
    );

    res.status(200).send({
      success: true,
      message: "Successfully retrieved products",
      data: products.map((product) => ({
        id: product.id as string,
        category: {
          value: product.category,
          label: ServerGlobal.getInstance().getCategoryLabel(product.category)!,
        },
        gender: {
          value: product.gender,
          label: ServerGlobal.getInstance().getGenderLabel(product.gender)!,
        },
        title: product.title,
        description: product.description,
        price: product.price,
        imageFilename: product.imageFilename,
      })),
    });
    return;
  } catch (e) {
    ServerGlobal.getInstance().logger.error(
      `<getProducts>: Failed to get products filtered by \
      category ${req.params.category} and gender ${req.params.gender} because of server error: ${e}`
    );

    res.status(500).send({
      success: false,
      message: "Server error",
    });
    return;
  }
};

推荐阅读