在for循环中以角度2链接http调用

新手上路,请多包涵

我有一些代码看起来像

//service.ts

addProduct(productId) {
   this.http.post('someUrl', ReqData).map(json).subscribe(doStuff);
}

//component.ts

addAllproducts(productsIds) {
   productIds.forEach(productId => service.addProduct(productId);
}

我想要的是能够在调用下一个 productId 之前等待每个调用完成,而不使用 window.setTimeout ..

原文由 AngularDebutant 发布,翻译遵循 CC BY-SA 4.0 许可协议

阅读 286
2 个回答

首先从您的服务方法返回可观察到的:

 addProduct(productId) {
   return this.http.post('someUrl', ReqData).map(json).subscribe(doStuff);
}

并使用递归函数并在数组中的每个项目的 subscribe 回调中调用它:

 let loop = (id: number) => {
  service.addProduct(id)
    .subscribe((result) => {
      // This logic can be modified to any way you want if you don't want to mutate the `producIds` array
      if (productIds.length) {
        loop(productIds.shift())
      }
    })
}

loop(productIds.shift())

原文由 Saravana 发布,翻译遵循 CC BY-SA 3.0 许可协议

使用 .expand() 进行一些递归调用怎么样?

首先,创建一个递归函数并映射数据以供递归使用:

 const recursiveAddProduct = (currentProductId, index, arr)=>{
    return service.addProduct(currentProductId)
        .map((response)=>{
            return {
                data:response,
                index: index+1,
                arr:arr
            }
        })
};

现在,在您的组件中递归调用它:

 //productIds is an array of Ids
//start of using the first index of item, where index = 0

let reduced = recursiveAddProduct(productIds[0],0,productIds)
    .expand((res)=>{
        return res.index>res.arr.length-1 ? Observable.empty(): recursiveAddProduct(productIds[res.index],res.index,productIds)
    });

reduced.subscribe(x=>console.log(x));

这是一个工作的 JSBin

使用 .expand 运算符的好处:

  1. 您仍在使用 Observables 并且可以链接任何您想要的运算符。
  2. 您正在一个接一个地调用 http,这是您的要求。
  3. 您无需担心错误处理,它们都链接到单个流。只需将 .catch 调用到您的可观察对象。
  4. 您可以对递归方法做任何事情(数据操作等)
  5. 您可以设置终止递归调用的条件。
  6. 一行(几乎)代码。

编辑

如果您不喜欢内联三元,您可以使用 .take() 运算符来终止递归,如下所示:

 let reduced = recursiveAddProduct(productIds[0],0,productIds)
    .expand(res=>recursiveAddProduct(productIds[res.index],res.index,productIds))
    .take(productIds.length)

工作 JSBin

原文由 CozyAzure 发布,翻译遵循 CC BY-SA 3.0 许可协议

撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进
推荐问题