Angular 2 : Nested subscribe with second subscribe inside the loop

标签 angular http request angular2-observables angular2-http

我刚接触 Angular2 一周!

基本上有 2 个 API 调用。

  1. 第一个 API 调用为我提供了一个 json 对象数组 (queryResults)。 (第一次订阅)
  2. 在 View 中显示该数组。
  3. 遍历 (queryResults) 数组并从每个数组元素 (queryResults[i].oldLastSeen) 中选择一个特定的键值对。
  4. 将该值 (oldLastSeen) 作为请求参数传递给另一个 API,它会给我一个字符串 (newLastSeen)。 (第二次订阅)
  5. 用queryResult中的newLastSeen替换oldLastSeen

由于 Observables 的异步性质,问题出现在第 5 步。我无法在内部订阅中访问 queryResults[i].oldLastSeen 并且基本上是未定义的。因此 lastSeen 不会更新。

从调用 getLastSeen() 开始, 代码如下所示:

temp: any[];
rows: any[];

getLastSeen() {
    this._someService.getQueryResults(this.query)
      .subscribe(queryResults => {
        this.rows = queryResults;
        this.updateLastSeen(this.rows);
      });
}

private updateLastSeen(rows) {
    this.temp = rows; //temp: any[];
    for(var i=0; i<this.temp.length; i++) {
        if(this.temp[i].id != null || this.temp[i].oldLastSeen != null) {
            //Some operations here
            this._someService.getNewLastSeen(this.temp[i].oldLastSeen)
                .subscribe(
                    newLastSeen => {
                        this.rows[i].oldLastSeen = newLastSeen; //This doesnot happen!
                    },
                    error => alert(error),
                    () => console.log("Finished.")
                );
        }
    }
  }

2 天以来一直在敲我的头,遇到了 flatMap、switchMap 等。但对它们的用法高度怀疑。

更新:工作代码:

我听从了 Bryan 的反馈,并对他建议的代码进行了一些修改。这是对我有用的:

this._someService.getQueryResults(this.query)
      .do(qr => {this.rows = qr;})
      .flatMap(queryResults => Observable.from(queryResults))
      .filter(queryItem => queryItem["id"] != null || queryItem["oldLastSeen"] != undefined)
      .do(queryItem => { // did some operations/ manipulations here})
      .mergeMap(queryItem => this._someService.getNewLastSeen(this.queryItem["oldLastSeen]),
           (queryItem, newLastSeen) => [queryItem, newLastSeen])
      .subscribe(([queryItem, newLastSeen]) => {
        queryItem.oldLastSeen = newLastSeen
      }); 

最佳答案

一般来说,如果您有嵌套订阅,那么您正在处理一个可以改进的反模式。我还没有找到一个令人信服的案例来使用它。我不确定对 flatMap 或 switchMap 持怀疑态度意味着什么,但它们是非常有用的运算符,尤其是 switchMap。如果您的工具包中没有 switchMap,您将无法做超出 rxjs 基础知识的事情。

getLastSeen() {
    this._someService.getQueryResults(this.query)
      .do(qr => this.rows = qr;)
      .flatMap(queryResults => Observable.from(queryResults))
      .filter(queryItem => queryItem.id !== null || queryItem.oldLastSeen !== null)
      // you can insert a map or do operator here to accomplish the operations you mention, depending on what they are, or you can possibly just do them inside switchMap
      .switchMap(queryItem => this._someService.getNewLastSeen(queryItem.oldLastSeen),
           (queryItem, newLastSeen) => [queryItem, newLastSeen])
      .subscribe(([queryItem, newLastSeen]) => queryItem.oldLastSeen = newLastSeen);

}

一点一点地看:

  1. 你得到你的查询

  2. 您将结果设置到 View 中。功能纯粹主义者会说在这里这样做是不好的做法,因为它会产生副作用,但无论如何。我不是纯粹主义者。

  3. 这很棘手,但您正在将结果扁平化为一系列可观察数据。您从结果数组创建一个可观察对象,然后 flatmap 一个一个地发出它们,您也可以在这里使用 .mergeAll() 。这是一种更具 react 性的循环结果方式。

  4. 过滤掉您不感兴趣的项目

  5. 您的“操作”的占位符行,可能是 map 或 do,在不知道所需效果的情况下很难说。也可能只在 switchMap 内部可行,但要注意样式和保持运算符简洁。

  6. switchMap 进入新的 observable,switchMap 将订阅内部 observable 并发出结果,关键是 switchMap 的第二个参数,它允许您组合来自内部和外部 observable 的项目。在这里我们只是将它们放入一个数组中并发出两个值的数组

  7. 重置订阅中的项目。这里唯一有趣的是使用 typescript 语法,让您可以命名数组中的项目,因为您知道您将获得一个包含 2 个项目的数组。

关于 Angular 2 : Nested subscribe with second subscribe inside the loop,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/45516125/

相关文章:

angular - 吴类 : if array contains item

rest - 202 Accepted 是对 http 补丁的可接受响应吗?

JavaScript 请求/操作框架还是工具包?

用于 HTTP 请求的 C++ 库 - XML、JSON、CSV

Angular2 - 在不同环境中执行端到端测试

javascript - 如何使用 typescript 映射和过滤数组上的不同值?

angular - 为什么我无法阻止用户编辑 PrimeNG 表单字段值?

actionscript-3 - 尝试通过套接字发送 HTTP 请求

http - 更改 http header 后浏览器发送 Options 而不是 Post

javascript - node.js 将 http 响应写入流