Warning: file_get_contents(/data/phpspider/zhask/data//catemap/1/angular/29.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/1/typescript/8.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Angular Rxjs使用延迟函数重试_Angular_Typescript_Rxjs - Fatal编程技术网

Angular Rxjs使用延迟函数重试

Angular Rxjs使用延迟函数重试,angular,typescript,rxjs,Angular,Typescript,Rxjs,我正在尝试使用retry和delay函数,我希望函数会在1000毫秒延迟后调用,但它没有,这里会有什么错误? 请看控制台输出,时间是16:22:48 我希望那里是16:22:48,16:22:59 canCreate: boolean; getSomeFunction(): Observable<boolean> { return new Observable<boolean>( observer => {

我正在尝试使用
retry
delay
函数,我希望函数会在1000毫秒延迟后调用,但它没有,这里会有什么错误? 请看控制台输出,时间是16:22:48

我希望那里是16:22:48,16:22:59

canCreate: boolean;
getSomeFunction(): Observable<boolean> {
        return new Observable<boolean>(
            observer => {
                const canCreate = null; // this is just null for now, will some value later
                if (canCreate == null) {
                    observer.error('error');
                } else {
                    observer.next(true);
                }
                observer.complete();
            }
        )
    }


this.getSomeFunction()
      .do((value) => {
        this.cCreate = value;
      }, (error) => {
         console.log(error + new Date().toTimeString());
      })
      .delay(1000)
      .retry(10)
      .subscribe(
        value => this.cCreate = value,
        error => {
          this.cCreate = false;
        },
        () => {}
      );
  }
canCreate:boolean;
getSomeFunction():可观察{
返回新的可观测数据(
观察员=>{
const canCreate=null;//现在这只是null,以后会有一些值吗
if(canCreate==null){
观察者错误(“错误”);
}否则{
观察者:下一个(正确);
}
observer.complete();
}
)
}
this.getSomeFunction()
.do((值)=>{
this.cCreate=值;
},(错误)=>{
log(错误+新日期().toTimeString());
})
.延迟(1000)
.重试(10)
.订阅(
value=>this.cCreate=value,
错误=>{
this.cCreate=false;
},
() => {}
);
}
结果是:

这可能会对您有所帮助

let values$ = Rx.Observable.interval(1000).take(5);
let errorFixed = false;

values$
.map((val) => {
   if(errorFixed) { return val; }
   else if( val > 0 && val % 2 === 0) {
      errorFixed = true;
      throw { error : 'error' };

   } else {
      return val;
   }
})
.retryWhen((err) => {
    console.log('retrying again');
    return err.delay(1000).take(3); // 3 times
})
.subscribe((val) => { console.log('value',val) });
用于在可观察对象发出的事件之间引入延迟。但可观测的物体从来不会发出任何事件。它只是立即出错

您需要的是,它允许您在重试多长时间后决定:

RxJS 5:

  .retryWhen(errors => errors.delay(1000).take(10))
  .retryWhen(errors => errors.delay(1000).take(10).concat(Observable.throw()))
RxJS 6:

import { retryWhen, delay, take } from 'rxjs/operators'
someFunction().pipe(
  // ...
  retryWhen(errors => errors.pipe(delay(1000), take(10)))
)
import { retryWhen, delay, take, concatMap, throwError } from 'rxjs/operators'
someFunction().pipe(
  // ...
  retryWhen(errors => errors.pipe(delay(1000), take(10), concatMap(throwError)))
)
这将在10次尝试后完成整个观察。如果要在10次尝试后对整个可观察对象出错,retryWhen回调返回的可观察对象必须抛出:

RxJS 5:

  .retryWhen(errors => errors.delay(1000).take(10))
  .retryWhen(errors => errors.delay(1000).take(10).concat(Observable.throw()))
RxJS 6:

import { retryWhen, delay, take } from 'rxjs/operators'
someFunction().pipe(
  // ...
  retryWhen(errors => errors.pipe(delay(1000), take(10)))
)
import { retryWhen, delay, take, concatMap, throwError } from 'rxjs/operators'
someFunction().pipe(
  // ...
  retryWhen(errors => errors.pipe(delay(1000), take(10), concatMap(throwError)))
)

我使用
retryWhen
Observable.Interval
提出了以下解决方案,但在这个解决方案中,
error
subscribe-never函数调用

this.branchService.getCanCreate()
  .do((value) => {
    this.cCreate = value;
  }, (error) => {
    console.log('do', error + new Date().toTimeString());
  })
  .retryWhen(errors => {
    return Observable.interval(1000).take(3).concat(Observable.throw('error')));
  })
  .subscribe(
    value => {
      this.cCreate = !!value
      console.log('success', new Date().toTimeString());
    },
    error => {
      console.log('subscribe', error + new Date().toTimeString());
      this.cCreate = false;
    },
    () => {
      console.log('finally', new Date().toTimeString());
    }
  );

添加到@JB Nizet的答案中。如果您是在rxjs 5+中使用lettable操作符编写的,请将其结构为


retryWhen(errors=>errors.pipe(延迟(1000),取(5))
对于ngrx5+我们可以创建操作符:


function retryRequest(constructor: () => Observable, count: number, delayTime: number) {
  let index = 0;
  return of(1) // we need to repeat not the result of constructor(), but the call of constructor() itself
    .pipe(
      switchMap(constructor),
      retryWhen(errors => errors.pipe(
        delay(delayTime),
        mergeMap(error => {
          if (++index > count) {
            return throwError(error);
          }
          return of(error);
        })
      ))
    );
}
适用于rxjs版本6.3.3

打开控制台并查看重试

示例代码


RxJS提供了
retry
操作符,当出现错误时,该操作符将重新订阅给定计数次数的可观测值。在抛出错误之前,
retry
操作符会针对给定的计数次数重新订阅可观测错误,如果仍然存在错误,则抛出错误<代码>重试对于多次点击URL很有用。由于网络带宽的原因,URL可能不会一次性返回成功的数据,而当它重新定时时,可能会成功返回数据。如果重试后,Observable中仍然存在错误,则可以使用
catchError
返回带有用户定义的默认数据的Observable

getBook(id:number):可观察{
返回此.http.get(this.bookUrl+“/”+id).pipe(
重试(3),
catchError(err=>{
控制台日志(err);
返回(空);
})
);
}

我最近遇到了这个问题,并发现可接受的解决方案可以改进

Observable.pipe(
     retryWhen(errors => errors.pipe(
      delay(1000),
      take(10))),
    first(v => true),
    timeout(10000))
它的基本功能是如前所述重试,但这会立即结束,而不会使用“first”运算符添加任何(错误的)值

如果在超时时间范围内找不到值,则会引发错误。

所有这些都是RxJS 6+


TL;博士 您可以使用此软件包中经过充分测试的运算符,或向下滚动查看源代码:)


标准 由于其他答案中的大多数(或者可能没有一个)不符合我的所有标准,我将在下面列出我的解决方案。目标:

  • 如果没有抛出错误,则定期发出并完成。✅
  • 如果抛出错误,则重试
    x
    次。✅
  • 每次重试前的延迟为
    y
    。✅
  • 返回上次发出的错误。(许多其他答案都在努力解决这个问题。)✅
  • strict:true
    正确输入–但这很难搞糟。✅

解决方案 与其他答案一样,我们将使用操作符捕捉错误。要跟踪重复次数,可以使用运算符。为了限制重复次数,我们只需在操作符中抛出一个错误

原始源代码使用,但在这种情况下,我们可以简单地使用from

最后,我们将使用运算符添加不同执行之间的延迟:

import { MonoTypeOperatorFunction } from 'rxjs';
import { delay as delayOperator, map, retryWhen, scan } from 'rxjs/operators';

export function retryWithDelay<T>(
  delay: number,
  count = 1
): MonoTypeOperatorFunction<T> {
  return (input) =>
    input.pipe(
      retryWhen((errors) =>
        errors.pipe(
          scan((acc, error) => ({ count: acc.count + 1, error }), {
            count: 0,
            error: undefined as any,
          }),
          map((current) => {
            if (current.count > count) {
              throw current.error;
            }
            return current;
          }),
          delayOperator(delay)
        )
      )
    );
}
import{MonoTypeOperatorFunction}从“rxjs”导入;
从'rxjs/operators'导入{delay as delayOperator,map,retryWhen,scan};
导出函数retryWithDelay(
延迟:数字,
计数=1
):单类型运算符函数{
返回(输入)=>
输入管道(
retryWhen((错误)=>
水管(
扫描((acc,error)=>({count:acc.count+1,error}){
计数:0,
错误:未定义为任何,
}),
地图((当前)=>{
如果(current.count>count){
抛出电流误差;
}
回流;
}),
delayOperator(延迟)
)
)
);
}

来源
  • –可能会派上用场

为了在http管道中重试其他操作,我得出了这个结论

import {delay as _delay, map, retryWhen} from 'rxjs/operators';

export const delayedRetry = (delay, retries = 1) => retryWhen(result => {
    let _retries = 0;
    return result.pipe(
      _delay(delay),
      map(error => {
        if (_retries++ === retries) {
          throw error;
        }
        return error;
      }),
    );
  },
);
用法


错误的类型是
可观察的
,它没有
完整的
方法我误解了文档。现在应该没事了。请看,我得到的是“提供的参数与调用目标的任何签名都不匹配。关于Observable.throw()”,因此“Observable.throw('error')对我有效,非常感谢您的回答。这对我无效。我一直得到
属性“concat”在类型“Observable”上不存在。
即使我导入了concat,
import”rxjs/add/observable/concat”
!以下是较新Angular/rxjs版本的完整代码:
pipe(retryWhen(error=>error.pipe(delay(1000)、take(3)、concat(Obser