2017-07-11 20 views
2

例如,假设我想进行一些API调用。我正在处理的api很容易出现竞争状况,所以如果我在同一时间更新服务器上的同一条数据时发出3个api调用,它可能会丢失一些数据。rxjs运算符与concatmap类似,但在发射下一个请求之前等待每个请求?

因此,我想排队我的请求,然后在发出下一个请求之前开启等待响应返回。

基本上我需要类似concatMap的东西,但concatMap的问题是它同时触发所有的请求。我需要concatMap在发射下一个请求之前等待。我正在使用rxjs 5.

这里是一个使用angular2的插入程序,您可以在其中单击按钮。当你点击1秒按钮时,一个观测值将被创建,并在1秒后返回。有2秒和3秒按钮。

https://plnkr.co/edit/6F4JrVueQX8PjPinZqIk?p=preview

@Component({ 
    selector: 'my-app', 
    template: ` 
    <div> 
     <h2>Wait:</h2> 

     <button (click)="start(1)">1 sec</button> 
     <button (click)="start(2)">2 sec</button> 
     <button (click)="start(3)">3 sec</button> 
    </div> 
    `, 
}) 
export class App { 


    constructor() { 
    } 

    start(wait) { 

    const waitSecs = parseInt(wait) * 1000; 

    of('clicked').delay(waitSecs).subscribe(
     val => console.log(wait) 
    ) 

    // Expected behavior: 
    // I click 3 sec, 2 sec, and 1 sec right after another. Then 
    // the console log should output 3, 2, 1. Right now it's 
    // outputting 1, 2, 3. 

    } 
} 

我点击3秒,2秒​​,并在之后将另1秒后,我与这个应用程序的理想行为会。然后控制台应该输出3,2,1。现在它是 输出1,2,3.

回答

3

既然你想拥有唯一的要求执行,你可以使用mergeMap()运营商与concurrency设置为1.请注意,这意味着待发送的项目将在您的mergeMap ope中排队rator会导致记忆问题。

Rx.Observable.from([3,5,2,1]) 
 
    .mergeMap(
 
    i => { 
 
     return Rx.Observable.of(i) 
 
     .do(i => console.log(`starting request for ${i}`)) 
 
     .delay(1000) 
 
     .do(null,null,() => console.log(`finished request for ${i}`)); 
 
    }, 
 
    null, 
 
    1 /* concurrency limited to 1 */ 
 
) 
 
    .subscribe(val => console.log(`received value: ${val}`));
<script src="https://cdnjs.cloudflare.com/ajax/libs/rxjs/5.4.2/Rx.js"></script>

+0

这个工程,我更新了我的掠夺者,我不再得到这个问题:https://plnkr.co/edit/EtC8czwAzhRaMEmrTG0s?p=preview – seescode

相关问题