Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/jquery-ui/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
如何使用RxJs使用多个异步任务对批量操作进行管道和调优?_Rxjs_Reactive Programming - Fatal编程技术网

如何使用RxJs使用多个异步任务对批量操作进行管道和调优?

如何使用RxJs使用多个异步任务对批量操作进行管道和调优?,rxjs,reactive-programming,Rxjs,Reactive Programming,比如说 购物车中有100种1-5个数量的产品,用户单击下订单 创建订单时,将执行以下任务: 以1对1的方式获取产品,以检查产品的可用性 检查并对每次购买10种产品的产品应用折扣 对每次购买50种产品的产品征收适用税 完成所有产品的计算后,计算订单总额 创建订单 注意:将产品添加到购物车时,可以向购物车添加多少物品是没有限制的,类似的任务也会在购物车中完成。我不完全确定您想要完成什么,但我想以下是您想要的: 假设以下是您的模型: 类产品{ id:编号; 名称:字符串; } 类产品订单{ 产品

比如说

  • 购物车中有100种1-5个数量的产品,用户单击下订单
  • 创建订单时,将执行以下任务:
  • 以1对1的方式获取产品,以检查产品的可用性
  • 检查并对每次购买10种产品的产品应用折扣
  • 对每次购买50种产品的产品征收适用税
  • 完成所有产品的计算后,计算订单总额
  • 创建订单

注意:将产品添加到购物车时,可以向购物车添加多少物品是没有限制的,类似的任务也会在购物车中完成。

我不完全确定您想要完成什么,但我想以下是您想要的:

假设以下是您的模型:

类产品{
id:编号;
名称:字符串;
}
类产品订单{
产品:产品;
数量:数量;
折扣:数量;
税种:数量;
}
阶级秩序{
productOrder:productOrder[];
总数:个;
}
考虑为每个步骤编写一个函数,其中每个函数的输入将是以前的输出:

/**
*检查产品的可用性,
*如果成功,则返回相同的@productOrder
*else抛出错误
*/
声明函数checkProductAvailability(productOrder:productOrder):可观察;
/**
*检查并应用产品折扣,
*将更改应用于@productOrder
*如果成功,则返回相同的@productOrder
*else抛出错误
*/
声明功能检查和应用折扣(productOrder:productOrder):可观察;
/**
*对产品征收适用税,
*将更改应用于@productOrder
*如果成功,则返回相同的@productOrder
*else抛出错误
*/
声明函数applyApplicableTaxes(productOrder:productOrder):可观察;
/**
*计算订单总数,
*如果成功返回@order
*else抛出错误
*/
声明函数CalculateOrderTotal(productOrder:productOrder[]):可观察;
/**
*创造秩序,
*如果成功回归
*else抛出错误
*/
声明函数createOrder(order:order):可观察;
具备上述功能后,剩下要做的就是将它们全部连接起来:

导入{
concatMap,
合并地图,
合并所有,
今天,
缓冲区计数,
捕捉错误,
}来自“rxjs/运营商”;
let productOrders:ProductOrder[];
来自(产品订单)
.烟斗(
concatMap(检查产品可用性),
缓冲计数(10),
mergeAll(),
concatMap(支票和应用折扣),
缓冲计数(50),
mergeAll(),
concatMap(适用于适用税),
toArray(),
合并映射(计算订单总数),
合并映射(createOrder),
catchError(errorHandler)
);

我已经制定了一个可能的解决方案,可以在中进行测试

这里是内嵌注释的逻辑

// this is the function that simulates a remote call to get the avalability of the 
// quantity requested for a certain item
function checkAvailability(prodId: string, qty: number) {
  // randomly decide if a product is available or not
  const prodAvailable = Math.random() > 0
  return  of(prodAvailable)
}

// this is the function that simulates a call to get the discound for batches of 10 products
// at the time (the last batch can have less then 10 products)
function discount(prodIds: string[]) {
  console.log('discount batch len', prodIds.length)
  // discount is fixed to be 10%
  const discounts = prodIds.map(p => 0.1)
  return of(discounts)
}

// this function simulates a call to get the tax for arrays of max 50 products
function taxes(prodIds: string[]) {
  console.log('taxes batch len', prodIds.length)
  // taxes are fixed to be 20%
  const taxes = prodIds.map(p => 0.2)
  return of(taxes)
}

// build the initial cart which contains 100 items - each item contains the product id 
// the quantity and the price (quantity and price as set to 1)
let cart: {prodId: string, qty: number, price: number}[] = new Array(100).fill(null)
cart = cart.map((_, i) => ({prodId: 'p' + i, qty: 1, price: 1}))

// this is the function that returns an Observabel which notifies the total of the order
function orderTotal$(cart: {
    prodId: string;
    qty: number;
    price: number;
}[])  { 
  // first we create a stream of items in the cart
  return from(cart).pipe(
    // for each item we call the function which returns the availability of the item
    // since the availability is calculated by an aync service, we use mergeeMap
    mergeMap(({prodId, qty, price}) => checkAvailability(prodId, qty).pipe(
      // we need to return not only the availability but also the rest of the data
      // so we pipe this map operator to enrich the data passed back
      map(available => ({available, prodId, qty, price}))
    )),
    // we filter only the available products
    filter(({available, prodId, qty}) => available),
    // buffer the items available in budders of 10
    bufferCount(10),
    // use mergeMap, as we do above, to retrieve the discount from the remote async service
    mergeMap(ar => {
      // return an object enriched wit the discound info
      return discount(ar.map(item => item.prodId)).pipe(
        map(discs => discs.map((disc, i) => ({...ar[i], disc})))
      )
    }),
    // use this merge mergeMap to tranform the emissions of batches of items with length 10
    // into a stream of 10 items
    mergeMap(ar => ar),
    // now create batched with size 50
    bufferCount(50),
    // use mergeMap to invoKe the remote service which returns the taxes
    mergeMap(ar => {
      const pIds = ar.map(item => item.prodId)
      return taxes(pIds).pipe(
        map(txs => txs.map((tax, i) => ({...ar[i], tax})))
      )
    }),
    // again use mergeMap to generare a strea  of 50 items
    mergeMap(ar => ar),
    // use reduce to calculate the order total
    reduce((orderTotal, item) => {
      const itemPrice = item.price
      orderTotal = orderTotal + (itemPrice - itemPrice * item.disc + itemPrice * item.tax) * item.qty
      return orderTotal
    }, 0)
  )
}

// subscribe to the result of orderTotal$ function to get the total of the orer
orderTotal$(cart).subscribe(d => console.log('order total', d))

这里的异步任务是什么?你能告诉我们你已经尝试过的代码以及你到底坚持到了哪里吗?RxJx新手,所以我想知道如果CheckAndApply折扣需要50个项目,ApplyAppliedTaxes需要10个项目,我该如何实现?请记住,在一天结束时,我们要处理流,一次处理一个项目,bufferCount用于等待特定数量的发射到达,然后让流继续流动