Angular 2 Http,Observables和递归请求

前端之家收集整理的这篇文章主要介绍了Angular 2 Http,Observables和递归请求前端之家小编觉得挺不错的,现在分享给大家,也给大家做个参考。
我有一个REST端点,它返回一个项目列表,一次最多1000个项目.如果有超过1000个项目,则响应具有HTTP状态206,并且我可以在下一个获取更多项目的请求中使用Next-Range标头.

我正在研究一个Angular 2应用程序并试图用Http和Observable实现它.我的问题是我不知道如何合并多个Observable,具体取决于有多少个页面,最后返回一个我的组件可以订阅的Observable.

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

// 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();
}@H_301_6@ 
 

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

您可以使用expand运算符实现此功能.你真正想要做的是创建一个递归的flatmap.这正是操作符扩展的目的.

以下是其工作原理的代码段:

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));@H_301_6@ 
 

我们做的是模拟第一个http请求,它具有true的’next’属性.这符合您的206标头.然后我们进行第二次调用,其中’next’属性为false.

结果是一个包含两个请求的结果的数组.由于扩展运算符,它也适用于更多请求.

工作jsbin示例可以在这里找到:http://jsbin.com/wowituluqu/edit?js,console

编辑:更新以使用从数组返回数组的http调用,最终结果是包含数组中所有元素的单个数组.

如果您希望结果中包含来自请求的单独数组的数组,只需删除flatmap并直接返回项目.在这里更新codepen:
http://codepen.io/anon/pen/xRZyaZ?editors=0010#0

猜你在找的Angularjs相关文章