Javascript RxJS每x秒从数组中发出一个值,使用该值调用一个函数,如果失败,请重试
我有一个数组,值的类型是无关的。我想做的是每x秒发出一个值,用该值调用一个函数,如果该函数由于某种原因失败,请在y秒后重试(可以是一个简单的常量,这里不需要任何增量) 到目前为止我所拥有的Javascript RxJS每x秒从数组中发出一个值,使用该值调用一个函数,如果失败,请重试,javascript,rxjs,rxjs5,Javascript,Rxjs,Rxjs5,我有一个数组,值的类型是无关的。我想做的是每x秒发出一个值,用该值调用一个函数,如果该函数由于某种原因失败,请在y秒后重试(可以是一个简单的常量,这里不需要任何增量) 到目前为止我所拥有的 Rx.Observable .interval(500) .take(arr.length) .map(idx => arr[idx]) .flatMap(dt => randomFunc(dt)) .catch(e => conosle.log(e)
Rx.Observable
.interval(500)
.take(arr.length)
.map(idx => arr[idx])
.flatMap(dt => randomFunc(dt))
.catch(e => conosle.log(e))
.retry(5)
.subscribe();
function randomFunc(dt) {
return Rx.Observable.create(observer => {
if (dt === 'random') {
return observer.error(`error`);
} else {
return observer.next();
}
});
}
但这里有两个问题:
1:当randomFunc
返回错误时,整个链似乎重新开始。我只需要失败的一个来重试
2:catch
从不实际记录任何错误,即使它似乎会在出现错误时重试
对于第一个问题,我尝试了switchMap
而不是flatMap
,如下所示:
Rx.Observable
.interval(500)
.take(arr.length)
.map(idx => arr[idx])
.switchMap(dt => randomFunc(dt)
.catch(e => conosle.log(e))
.retry(5)
)
.subscribe();
通过这种方式,它似乎只重试了失败的部分,但仍然没有记录任何错误,我甚至不确定switchMap
在这里是否好(我真的是一个Rx noob)
任何帮助都将不胜感激,谢谢
当randomFunc
返回错误时,整个链似乎开始运行
结束我只需要失败的一个来重试`
在RxJs中,当将观测值组合在一起时,错误也会传播,未捕获的错误会导致取消订阅
您在开关映射中使用catch的想法是正确的。虽然switchMap
一次只展平一个可观测值,但当下一个值被映射时,上一个可观测值将被取消订阅(它被关闭)
//可从数组中观察到
从(arr)可观察到的接收
.concatMap(值=>
//在每个值之间设置500毫秒的延迟
Rx.Observable.timer(500).map(=>value)
)
.flatMap(dt=>
随机函数(dt)
.retryWhen(错误=>
错误
.do(err=>console.error(err))
//最多重试5次
.采取(5)
//500毫秒后重试
.延迟(500)
)
)
.subscribe();
catch实际上从不记录任何错误,即使它似乎在上重试
错误
传递给catch的函数应返回一个可观察的值,例如:
Observable.throw(新错误())
.catch(e=>
(控制台错误(e),可观察到(‘备份值’)
)
.subscribe();
有几件事需要注意。retry()
操作符只需重新订阅其源代码,因此如果不想再次开始整个迭代,可以将/concat异步函数合并到链中
Rx.Observable.from(arr)
.concatMap(val => {
let attempts = 0;
return Rx.Observable.of(val)
.delay(500)
.concatMap(val => randomFunc(val)
.catch((err, caught) => {
console.log('log error');
if (attempts++ === 1) {
return Rx.Observable.of(err);
} else {
return caught;
}
})
);
})
.subscribe(val => console.log(val));
function randomFunc(dt) {
return Rx.Observable.create(observer => {
if (dt === 'random') {
observer.error(`error received ${dt}`);
} else {
observer.next(dt);
observer.complete();
}
});
}
见现场演示:
这将打印到控制台:
1
2
3
4
log error
log error
error received random
6
7
8
9
10
catch()
操作符是最重要的部分。其选择器函数具有两个参数:
err
-发生的错误
捕获
-原始可观察到的
如果我们从选择器函数返回catch
,我们只需重新订阅可观察的源代码(这与retry(1)
)相同)。由于要记录每个错误消息,我们必须使用catch()
,而不仅仅是retry()
。通过返回(err)
的Rx.Observable.of(err)
我们进一步传播错误,然后订阅者将收到该错误作为下一个
通知。我们也可以只返回Observable.empty()
来忽略错误。catch
可能没有记录,因为控制台拼写错误:-)conosle=>console