继续订阅出错后的处理方式

3

我有一段代码,在这段代码中,我为每个ID发起一个ajax请求,并在结果返回时对它们进行处理。这是我实际代码的简单复制品和jsfiddle

var ids = [1,2,3,4,5,6];
var ids$ = (id) => {
    return Observable.of(id);
};
var loadIds$ = (id) => {
    if(id == 4) return xhr('/echo/jsoneee/', {id: id});
    return xhr('/echo/json/', {id: id});
};

Observable.from(ids)
.concatMap(id => Observable.forkJoin(ids$(id), loadIds$(id)))
.catch((err, caught) => {
  //get the id for which loadIds failed
  //send the id to subscribe() and continue the subscription
  return Observable.empty();
})
.subscribe(result => console.log(result))

现在我需要修改代码,如果发生错误,我需要获取ajax请求失败的id,然后就像什么也没发生一样继续订阅。但我还没有能够做到这一点。非常感谢帮助。


这段代码是用来做什么的?.concatMap(id => Observable.forkJoin(ids$(id), loadIds$(id))) - martin
@martin 这只是一个模拟,以使事情更简单。但它可以是 forkJoinzip,但目的是 subscribe() 应该将 id 对象和该 id ajax 请求的响应作为单个项目一起传递,因为我在 subscribe 中进行其他处理,我需要这两个数据。 - lbrahim
1个回答

3
我认为你可以通过在Observable.create(...) 中直接发出正确的值来显著简化这个过程:
function xhr(url, json) {
    return Observable.create(function (observer) {
        $.ajax({
            url: url,
            data: JSON.stringify(json),
            success: function (response) {
                observer.next([json.id, json]);
            },
            error: function (jqXHR, status, error) {
                observer.next([json.id]); // <== Notice this
            },
            complete: function () {
                observer.complete();
            }
        });
    });
}

var ids = [1,2,3,4,5,6];
var ids$ = (id) => {
    return Observable.of(id);
};
var loadIds$ = (id) => {
    if(id == 4) return xhr('/echo/jsoneee/', {id: id});
    return xhr('/echo/json/', {id: id});
};

Observable.from(ids)
    .concatMap(id => loadIds$(id))
    .subscribe(result => console.log(result));

这样,您可以完全避免使用forkJoin()。同时要注意,catch()操作符会自动取消其源的订阅。此操作符旨在继续使用另一个Observable,因此在像您这样的情况下非常有用。
当然,您也可以使用:
.catch((error, caught) => {
    return caught;
})

然而,这会导致重新订阅和从头开始重新发出所有值,这通常是不需要的。

还有一个onErrorResumeNext()操作符,它可以简单地忽略错误,但这可能不是您想要的。

请参见演示:https://jsfiddle.net/4f1zmeyd/1/

一个稍微类似的问题:获取新票据,然后重试第一个请求


我宁愿不根据这个例子修改xhr()。但是我不确定为什么这个catch不能按照我想要的方式工作?https://jsfiddle.net/ibrahimislam/ecLp6h1u/ - lbrahim
@lbrahim,你不能使用catch()使其正常工作,因为它无法实现你想要的功能。 - martin
但是如果您查看此示例:https://jsfiddle.net/ibrahimislam/ecLp6h1u。它按预期工作。 - lbrahim
@lbrahim 不一样。这只是忽略错误并继续,而不在响应中包括失败的id。如果根本不使用catch(),只使用onErrorResumeNext(),你将得到完全相同的结果。 - martin

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接