Angular 2 Http,Observables和递归请求 [英] Angular 2 Http, Observables and recursive requests

查看:67
本文介绍了Angular 2 Http,Observables和递归请求的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个REST端点,该端点可以返回项目列表,一次最多返回1000个项目.如果有1000个以上的项目,则响应的HTTP状态为206,并且有一个Next-Range标头,我可以在下一个请求中使用它来获取更多的项目.

I have a REST endpoint that returns a list of items, max 1000 items at a time. If there are more than 1000 items, the response has HTTP status 206 and there's a Next-Range header that I can use in my next request for getting more items.

我正在开发 Angular 2应用程序,并尝试使用HttpObservable来实现它.我的问题是我不知道如何如何合并多个Observable ,具体取决于有多少页项目并且最终返回一个Observable 我的组件可以订阅.

I'm working on an Angular 2 application and trying to implement this with Http and Observable. My problem is that I don't know how to merge multiple Observables depending on how many pages of items there are and finally return one Observable that my component can subscribe to.

这是我当前的TypeScript实现的地方:

Here's where I've got with my current TypeScript implementation:

// NOTE: Non-working example!

getAllItems(): Observable<any[]> {
  // array of all items, possibly received with multiple requests
  const allItems: any[] = [];

  // inner function for getting a range of items
  const getRange = (range?: string) => {
    const headers: Headers = new Headers();
    if (range) {
      headers.set('Range', range);
    }

    return this.http.get('http://api/endpoint', { headers })
      .map((res: Response) => {
        // add all to received items
        // (maybe not needed if the responses can be merged some other way?)
        allItems.push.apply(allItems, res.json());

        // partial content
        if (res.status === 206) {
          const nextRange = res.headers.get('Next-Range');

          // get next range of items
          return getRange(nextRange);
        }

        return allItems;
      });
  };

  // get first range
  return getRange();
}

但是,这不起作用.如果我正确理解,则会返回Observable作为初始Observable的值,而不是项目数组.

However, this doesn't work. If I understood it correctly, an Observable is returned as the value of the initial Observable and not the array of items.

推荐答案

您可以使用expand运算符实现此目标.您实际要做的是创建一个递归平面图.这正是创建操作员扩展的目的.

You can implement this using the expand operator. What you actually want to do is create a recursive flatmap. That's exactly what the operator expand was created for.

这是其工作方式的代码段:

Here is the code snippet of how this works:

let times = true;
// This is a mock method for your http.get call
const httpMock = () => {
  if(times) {
    times = false;
    return Rx.Observable.of({items: ["1", "2", "3"], next: true});
  } else {
    return Rx.Observable.of({items: ["4", "5", "6"], next: false});
  }
}

httpMock()
  .expand(obj => {
    // In your case, the obj will be the response
    // implement your logic here if the 206 http header is found
    if(obj.next) {
      // If you have next values, just call the http.get method again
      // In my example it's the httpMock
      return httpMock();
    } else {
      return Rx.Observable.empty();
    }
  })
  .map(obj => obj.items.flatMap(array => array)) 
  .reduce((acc, x) => acc.concat(x), []);
  .subscribe((val) => console.log(val));

做什么是模拟第一个http请求,该请求具有'next'属性为true.这与您的206标头匹配.然后,我们进行第二个调用,该调用的'next'属性设置为false.

What is does is mock a first http request, that has a 'next' property to true. This matches your 206 header. We then make a second call which has the 'next' property to false.

结果是一个数组,其中包含两个请求的结果.多亏了expand运算符,它也适用于更多请求.

The result is an array containing the results from both the requests. It's applicable for more requests as well thanks to the expand operator.

可运行的jsbin示例可在以下位置找到: http://jsbin.com/wowituluqu/edit? js,控制台

Working jsbin example can be found here: http://jsbin.com/wowituluqu/edit?js,console

已更新,可与http调用一起使用,该调用从数组中返回一个数组,最终结果是一个包含数组中所有元素的单个数组.

updated to work with an http call that returns an array from arrays and the end result is a single array that contains all the elements form the arrays.

如果结果是希望将一个数组与请求中的单独数组一起放置在内部,则只需删除平面图并直接返回项目即可.在此处更新codepen: http://codepen.io/anon/pen/xRZyaZ?editors=0010#0

If you wish to have as a result an array with the separate arrays from the request still inside, just remove the flatmap and return the items directly. Update codepen here: http://codepen.io/anon/pen/xRZyaZ?editors=0010#0

这篇关于Angular 2 Http,Observables和递归请求的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆