Javascript RxJS重试未按预期运行?
我很难让RxJS的重试操作符与map操作符一起工作 本质上,我试图做的是获取一个值流(在本例中,GitHub用户用于测试目的),并对每个值对该值执行一些操作 但是,我希望能够以允许我为该操作设置有限重试次数的方式处理错误。我还假设RxJS异步处理这样的事情Javascript RxJS重试未按预期运行?,javascript,rxjs,reactive-programming,Javascript,Rxjs,Reactive Programming,我很难让RxJS的重试操作符与map操作符一起工作 本质上,我试图做的是获取一个值流(在本例中,GitHub用户用于测试目的),并对每个值对该值执行一些操作 但是,我希望能够以允许我为该操作设置有限重试次数的方式处理错误。我还假设RxJS异步处理这样的事情 Rx.Observable.fromPromise(jQuery.getJSON("https://api.github.com/users")) .concatAll(x => Rx.Observable.of(x)) .map(x
Rx.Observable.fromPromise(jQuery.getJSON("https://api.github.com/users"))
.concatAll(x => Rx.Observable.of(x))
.map(x => {
if(x.id % 5 == 0) {
console.log("error");
return Rx.Observable.throw("error");
}
return x;
})
.retry(3)
.subscribe(x => console.log(x), e => console.log(e));
这就是我到目前为止得到的,但是它应该重试相同的值3次,它只打印“错误”一次,这不是我正在寻找的行为
我是否遗漏了一些琐碎的东西,或者RxJS根本不可能做到这一点?简言之,我希望异步执行对值的操作,将所述操作重试有限次,但允许其他有效操作并行进行。我仅使用Promissions实现了类似的功能,但代码相当混乱,我希望RxJS能让我的阅读变得更流畅。我发现一些问题可能会给您带来问题: 1) 在map语句中,您通过返回一个可观察值进行抛出。如果成功案例也返回了一个可观察值,然后将其展平(使用concat、switch或merge),那么这将是合适的,但是您的成功案例只会发出一个值,而不会展平。因此,当抛出的可观察对象被返回时,它永远不会被展平,因此只会被传递并记录可观察对象
相反,您可以只做一个普通的JavaScript <代码>抛出“错误”<代码>(尽管考虑抛出一个错误对象而不是一个字符串)
2) 当重试收到错误时,它将重新订阅。如果您使用可观察对象进行抓取,这将意味着它将再次进行抓取。但是,您使用承诺进行了获取,然后仅根据该承诺创建了一个可观察的。因此,当您重新订阅observable时,它将使用第一次使用的promise对象,并且该promise已经处于解析状态。不会进行额外提取 要解决这个问题,您需要有一个可观察版本的获取。如果需要从头开始制作,它可以如下所示:Rx.Observable.create(observer => {
jQuery.getJSON("https://api.github.com/users")
.then(result => {
observer.next(result);
observer.complete();
}, err => {
observer.error(err);
observer.complete();
});
})
function getJson (url) {
return Rx.Observable.create(observer) => {
jQuery.getJSON(url)
.then(result => {
observer.next(result);
observer.complete();
}, err => {
observer.error(err);
observer.complete();
});
}
}
const endpoints = ['someUrl', 'someOtherUrl'];
const observables = endpoints.map(endpoint =>
return getJson(url)
.retry(3)
.catch(err => Rx.Observable.of('error'));
});
Rx.Observable.forkJoin(...observables)
.subscribe(resultArray => {
// do whatever you need to with the results. If any of them
// errored, they will be represented by just the string 'error'
});
不过,如果您打算经常这样做,我建议您创建一个函数来完成包装
编辑:
我的最终目标是基本上能够获取api URL数组,并使用每个URL启动get请求。如果get请求由于任何原因失败,它应该尝试总共3次以再次到达该端点。然而,这样一个get请求的失败不应该阻止其他请求的发生,它们应该并行发生。此外,如果一个get请求失败了3次,它应该被标记为失败,而不应该停止整个过程。到目前为止,我还没有找到一种使用RxJS的方法 然后我会这样做:
Rx.Observable.create(observer => {
jQuery.getJSON("https://api.github.com/users")
.then(result => {
observer.next(result);
observer.complete();
}, err => {
observer.error(err);
observer.complete();
});
})
function getJson (url) {
return Rx.Observable.create(observer) => {
jQuery.getJSON(url)
.then(result => {
observer.next(result);
observer.complete();
}, err => {
observer.error(err);
observer.complete();
});
}
}
const endpoints = ['someUrl', 'someOtherUrl'];
const observables = endpoints.map(endpoint =>
return getJson(url)
.retry(3)
.catch(err => Rx.Observable.of('error'));
});
Rx.Observable.forkJoin(...observables)
.subscribe(resultArray => {
// do whatever you need to with the results. If any of them
// errored, they will be represented by just the string 'error'
});
我发现一些可能会给您带来问题的问题: 1) 在map语句中,您通过返回一个可观察值进行抛出。如果成功案例也返回了一个可观察值,然后将其展平(使用concat、switch或merge),那么这将是合适的,但是您的成功案例只会发出一个值,而不会展平。因此,当抛出的可观察对象被返回时,它永远不会被展平,因此只会被传递并记录可观察对象
相反,您可以只做一个普通的JavaScript <代码>抛出“错误”<代码>(尽管考虑抛出一个错误对象而不是一个字符串)
2) 当重试收到错误时,它将重新订阅。如果您使用可观察对象进行抓取,这将意味着它将再次进行抓取。但是,您使用承诺进行了获取,然后仅根据该承诺创建了一个可观察的。因此,当您重新订阅observable时,它将使用第一次使用的promise对象,并且该promise已经处于解析状态。不会进行额外提取 要解决这个问题,您需要有一个可观察版本的获取。如果需要从头开始制作,它可以如下所示:Rx.Observable.create(observer => {
jQuery.getJSON("https://api.github.com/users")
.then(result => {
observer.next(result);
observer.complete();
}, err => {
observer.error(err);
observer.complete();
});
})
function getJson (url) {
return Rx.Observable.create(observer) => {
jQuery.getJSON(url)
.then(result => {
observer.next(result);
observer.complete();
}, err => {
observer.error(err);
observer.complete();
});
}
}
const endpoints = ['someUrl', 'someOtherUrl'];
const observables = endpoints.map(endpoint =>
return getJson(url)
.retry(3)
.catch(err => Rx.Observable.of('error'));
});
Rx.Observable.forkJoin(...observables)
.subscribe(resultArray => {
// do whatever you need to with the results. If any of them
// errored, they will be represented by just the string 'error'
});
不过,如果您打算经常这样做,我建议您创建一个函数来完成包装
编辑:
我的最终目标是基本上能够获取api URL数组,并使用每个URL启动get请求。如果get请求由于任何原因失败,它应该尝试总共3次以再次到达该端点。然而,这样一个get请求的失败不应该阻止其他请求的发生,它们应该并行发生。此外,如果一个get请求失败了3次,它应该被标记为失败,而不应该停止整个过程。到目前为止,我还没有找到一种使用RxJS的方法 然后我会这样做:
Rx.Observable.create(observer => {
jQuery.getJSON("https://api.github.com/users")
.then(result => {
observer.next(result);
observer.complete();
}, err => {
observer.error(err);
observer.complete();
});
})
function getJson (url) {
return Rx.Observable.create(observer) => {
jQuery.getJSON(url)
.then(result => {
observer.next(result);
observer.complete();
}, err => {
observer.error(err);
observer.complete();
});
}
}
const endpoints = ['someUrl', 'someOtherUrl'];
const observables = endpoints.map(endpoint =>
return getJson(url)
.retry(3)
.catch(err => Rx.Observable.of('error'));
});
Rx.Observable.forkJoin(...observables)
.subscribe(resultArray => {
// do whatever you need to with the results. If any of them
// errored, they will be represented by just the string 'error'
});
map函数返回
Rx.Observable.throw(“错误”)代码>。这是错误的,因为下面的retry()
随后将接收到它的包装(即作为Observable
而不是Observable
。您可以使用flatMap
来纠正这一点,但是您还需要通过Rx.Observable.of(x)
包装该值
另一个选项是抛出新错误()
,而不是尝试返回Rx.Observable.throw(“错误”);
确保您在正确的事情上重试
Rx.Observable.fromPromise(jQuery.getJSON("https://api.github.com/users"))
.retry(3)
.concatAll(x => Rx.Observable.of(x))
...
您的map函数返回Rx.Observable.throw(“error”);
。这是错误的,因为下面的retry()
随后将接收包装的值(即作为Observable
而不是Observable
。您可以使用flatMap
来纠正这一点,但您还需要通过Rx.Observable.of(x)包装该值
另一个选项是抛出新错误()
,而不是tryi