RxJs-如何使可观察行为像队列一样

RxJs-如何使可观察行为像队列一样,rxjs,queue,rxjs6,Rxjs,Queue,Rxjs6,我正在努力实现下一个目标: private beginTransaction(): Observable() { .. } private test(): void { this.beginTransaction().subscribe((): void => { this.commitTransaction(); }); this.beginTransaction().subscribe((): void => { this.commitTra

我正在努力实现下一个目标:

private beginTransaction(): Observable() {
  ..
}

private test(): void {
  this.beginTransaction().subscribe((): void => {
    this.commitTransaction();
  });

  this.beginTransaction().subscribe((): void => {
     this.commitTransaction();
  });
}
可以同时调用beginTransaction,但应将可观察对象延迟到第一次或只有一次beginTransaction完成。

顺序词:任何时候只能进行一次交易。

我试过什么:

private transactionInProgress: boolean = false;
private canBeginTransaction: Subject<void> = new Subject<void>();

private bla3(): void {

  this.beginTransaction().subscribe((): void => {
    console.log('beginTransaction 1');
    this.commitTransaction();
  });

  this.beginTransaction().subscribe((): void => {
    console.log('beginTransaction 2');
    this.commitTransaction();
  });

  this.beginTransaction().subscribe((): void => {
    console.log('beginTransaction 3');
    this.commitTransaction();
  });
}

private commitTransaction(): void {
  this.transactionInProgress = false;
  this.canBeginTransaction.next();
}

private beginTransaction(): Observable<void> {

  if(this.transactionInProgress) {
    return of(undefined)
    .pipe(
      skipUntil(this.canBeginTransaction),
      tap((): void => {
        console.log('begin transaction');
      })
    );
  }
  this.transactionInProgress = true;
  return of(undefined);
}
private transactionprogress:boolean=false;
private canBeginTransaction:Subject=新Subject();
私有bla3():void{
this.beginTransaction().subscribe(():void=>{
console.log('beginTransaction 1');
this.commitTransaction();
});
this.beginTransaction().subscribe(():void=>{
console.log('beginTransaction 2');
this.commitTransaction();
});
this.beginTransaction().subscribe(():void=>{
console.log('beginTransaction 3');
this.commitTransaction();
});
}
private commitTransaction():void{
this.TransactionProgress=false;
this.canBeginTransaction.next();
}
私有beginTransaction():可观察{
如果(此事务处理进度){
返回(未定义)
.烟斗(
skipUntil(这是一个可以启动的动作),
点击(():无效=>{
log('begintransaction');
})
);
}
this.TransactionProgress=true;
返回(未定义);
}

我不确定我是否正确理解了这个问题,但在我看来,
concatMap
就是您要找的操作员

下面是一个例子

const transactionTriggers$ = from([
  't1', 't2', 't3'
])

function processTransation(trigger: string) {
  console.log(`Start processing transation triggered by ${trigger}`)
  // do whatever needs to be done and then return an Observable
  console.log(`Transation triggered by ${trigger} processing ......`)
  return of(`Transation triggered by ${trigger} processed`)
}

transactionTriggers$.pipe(
  concatMap(trigger => processTransation(trigger)),
  tap(console.log)
).subscribe()
您基本上从一个事件流开始,其中每个事件都应该触发事务的处理

然后使用
processTransaction
函数执行处理事务所需的任何操作
processTransactio
需要返回一个Observable,当事务处理完成后,它会发出处理结果

然后在管道中,如果需要,可以使用
点击
,对处理结果进行进一步处理


您可以在中尝试代码。

我不确定我是否正确理解了问题,但在我看来,
concatMap
就是您要找的操作员

下面是一个例子

const transactionTriggers$ = from([
  't1', 't2', 't3'
])

function processTransation(trigger: string) {
  console.log(`Start processing transation triggered by ${trigger}`)
  // do whatever needs to be done and then return an Observable
  console.log(`Transation triggered by ${trigger} processing ......`)
  return of(`Transation triggered by ${trigger} processed`)
}

transactionTriggers$.pipe(
  concatMap(trigger => processTransation(trigger)),
  tap(console.log)
).subscribe()
您基本上从一个事件流开始,其中每个事件都应该触发事务的处理

然后使用
processTransaction
函数执行处理事务所需的任何操作
processTransactio
需要返回一个Observable,当事务处理完成后,它会发出处理结果

然后在管道中,如果需要,可以使用
点击
,对处理结果进行进一步处理


您可以在中尝试代码。

您所询问的内容非常模糊和笼统。毫无疑问,一个更受约束的场景可能看起来简单得多

无论如何,我在这里创建了一个管道,它一次只允许订阅一次
transaction():Observable

这可能看起来是这样的:

/****
*表示每个事务的功能。不关心
*订单/时间/交易进度或诸如此类的事情。
* 
*这是一个伪事务,只需3-5秒即可发出
*字符串:`Hello${name}`
****/
函数事务(args):可观察{
const name=args?.message;
常数持续时间=3000+(Math.random()*2000);
返回(“你好”)管道(
点击(=>console.log(“启动事务”),
开关映射(v=>计时器(持续时间).pipe(
映射(=>`${v}${name}`)
)),
轻触(=>console.log(“结束交易”))
);
}
//跟踪交易
让currentTransactionId=0;
//启动交易
const transactionSubj=新主题();
//执行事务:concatMap确保我们只在以下情况下启动一个新事务
//当前没有正在进行的交易
const transaction$=transactionSubj.pipe(
concatMap({id,args})=>transaction(args).pipe(
映射(有效负载=>({id,有效负载}))
)),
共享重播(1)
);
/****
*开始一个新的事务,我们给它一个ID,因为事务是
*“热”,我们不想返回错误的(早期)交易,
*只有当前的一个以此呼叫开始。
****/
函数beginTransaction(args):可观察{
返回延迟(()=>{
const currentId=currentTransactionId++;
transactionSubj.next({id:currentId,args});
返回事务处理$.pipe(
第一个({id}=>id==currentId),
map({payload})=>payload)
);
})
}
//排队3个事务,每个事务将等待上一个事务
//在开始之前先完成一个。
beginTransaction({message:“Dave”}).subscribe(console.log);
beginTransaction({message:“Tom”}).subscribe(console.log);
beginTransaction({message:“Tim”}).subscribe(console.log);
异步事务 当前设置要求事务是异步的,否则可能会丢失第一个事务。解决这个问题的方法并不简单,所以我构建了一个订阅的操作符,然后尽快调用一个函数

这是:

函数初始化(fn:()=>void):单类型运算符函数{
返回s=>新的可观察对象(观察者=>{
const bindOn=name=>observer[name].bind(observer);
const sub=s.subscribe({
下一个:宾顿(“下一个”),
错误:bindOn(“错误”),
完成:宾顿(“完成”)
});
fn();
返回{
取消订阅:()=>sub.unsubscribe
};
});
}
现在正在使用:

function beginTransaction(args):可观察{
返回延迟(()=>{
const currentId=currentTransactionId++;
返回事务处理$.pipe(
初始化(()=>transactionSubj.next({id:currentId,args})),
第一个({id}=>id==currentId),
map({payload})=>payload)
);
})
}
旁白:为什么要使用延迟? 考虑重新写入beginTransaction:

function beginTransaction(args):可观察{
常数currentId=currentTrans