2016-09-30 88 views
4

我已阅读Rx.js repeat文档,以了解如何根据我从API收到的响应来继续调用api。我打电话API,一次只能发回2k记录。 API会发回一个值给我发送它,以便我可以继续接收记录,直到它们返回完成值。Observable继续调用API并根据条件更改参数

所以流程进入如下:

  1. 拨打GET请求的查询参数reqMode=''
  2. 检索响应与含有reqModevaluedone最后阵列。
  3. 如果我收到value,那么我需要提出同样的请求,但发送reqMode参数的值。
  4. 如果我收到done,那么我将停止并返回自第一次通话以来的所有记录。

我得到的第一组值时subscribing normally,但阅读文档后,这将是我的尝试,但它没有任何意义:

getRecords(){ 
    let url = this.url + 'reqMode='; 
    return this.http.get(url) 
      .doWhile() //What would I do here 
} 

当试图做.doWhile具有可观察那就是Observable<response>。我正在寻找任何使用Observables来替代我需要做的选择。

+0

angular2附带rxjs5-β和基于您将无法使用.doWhile文档中......至少目前还没有:https://github.com/ReactiveX/rxjs/blob/master/MIGRATION.md#operators-renamed-or-removed。你在寻找替代解决方案吗?或只为rxjs4? – mrcolombo

+0

我很好,有替代品。 – inspired

回答

4

我不认为repeat()是一个很好的运营商。如果我正确理解你,你想重复基于前一个请求的响应的HTTP请求。如果您想多次重复相同的请求,则运算符repeat()是很好的。

我会使用concatMap()和递归调用本身,直到reqMode是eqaul到"done"

见现场演示:http://plnkr.co/edit/w0DdepslTaKrLSB3aIkA

import {Observable, Subject} from 'rxjs'; 

const result = new Subject(); 
const closeBuffer = new Subject(); 
const buffer = result.buffer(closeBuffer.asObservable()); 

function sendHttpRequest(reqMode) { 
    return Observable.of('{"reqMode":' + reqMode + '}') 
    .map(response => JSON.parse(response)) 
    .concatMap(data => { 
     console.log('HTTP Response:', data); 
     // Add data to the buffer of results 
     result.next(data); 

     if (data.reqMode == 'done') { 
     // Return an empty value wrapped as an Observable so concatMap can work 
     // with it and emit onNext when it completes (which is immediately 
     // thanks to the `.of()` operator). 
     return Observable.of(null); 
     } else { 
     // Simulate that the next call returns 'done' 
     return sendHttpRequest('"done"'); 

     // Uncomment this for real usage 
     //return sendHttpRequest(data.reqMode); 
     } 
    }); 
} 

// Subscribe to the buffer where I'll receive the value. 
buffer.subscribe(val => console.log('Next: ', val)); 

// Simulate HTTP request with reqMode = 42 
sendHttpRequest(42).subscribe(() => { 
    console.log('done'); 
    // Emit values from the buffer. 
    closeBuffer.next(null); 
    closeBuffer.complete(); 
}); 

我用of()操作模拟一个请求,并返回一个值包装成一个Observable。我还使用Subject来保存使用buffer()运算符缓冲的所有响应。我订阅缓冲区以获得最终的响应数组(如果将此代码封装到函数中,您很可能会返回buffer,您可以在其中稍后订阅)。

的响应如下:

HTTP Response: Object {reqMode: 42} 
HTTP Response: Object {reqMode: "done"} 
Next: [Object, Object] 

见类似的问题:Angular 2 + rxjs - how return stream of objects fetched with several subsequent http requests

+0

看起来不错! '递归'一直是我的一个弱点。现在是时候进入一个新的...我现在尝试这一个 – inspired

+0

@inspired我更新了我的答案,我没有意识到你想堆叠所有的回应,直到'完成'这意味着可能有多个我猜( ?)现在有点复杂了,但我认为它仍然可以理解。 – martin

+0

哦,我正在尝试你的方法,只是将每个数据响应都推送到一个数组中,以便将它们全部收集起来,但我想这会将我的方法耦合到外部数组。 – inspired

2

所以我举例说明了如何使用包装observer和使用.repeat()来做到这一点。

所有的逻辑是app.component.ts

Checkout this plunker

我离开代码中的注释,但本质上它将使一个HTTP请求,它会增加一个数,然后将与不同的另一个请求查询号码。它会重复,直到它达到5.

您将不得不修改它,以便“重复条件”代表您的逻辑。

希望有帮助!

+0

好吧,让我试试看。 – inspired

+0

@mrcolombo - 你会如何增加一个时间间隔,以便每秒重复一次? –

+0

@DonalRafferty在'.repeat()'将每秒执行一次之前添加'.delay(1000)'。 – mrcolombo