2016-11-14 2 views
3

У меня есть код, в котором для каждого из идентификаторов я делаю запрос 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)) 

Но теперь мне нужно изменить код, чтобы при возникновении ошибки мне пришлось получить id, для которого не удалось выполнить запрос ajax, а затем просто продолжить подписку, как будто ничего не произошло. Я еще не смог этого сделать. Помощь очень ценится.

+0

Что это должен делать '.concatMap (ID => Observable.forkJoin (ID $ (ID), loadIds $ (идентификатор))) '? – martin

+0

@martin Это всего лишь макет, чтобы сделать вещи проще. Но это может быть 'forkJoin' или' zip', но цель состоит в том, что 'subscribe()' должен иметь объект 'id' и ответ для этого' id' ajax-запроса как единый элемент вместе, потому что я делаю другую обработку внутри подписаться, и мне нужны обе данные. – lbrahim

ответ

2

Я думаю, вы можете упростить это значительно испуская правильные значения прямо в 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/

Немного похожий вопрос: get new ticket then retry first request

+0

Я бы предпочел не модифицировать 'xhr()' в соответствии с этим примером. Но я не уверен, почему это работает, хотя я хочу, чтобы это было с 'catch'? https://jsfiddle.net/ibrahimislam/ecLp6h1u/ – lbrahim

+0

@lbrahim. Вы не получите его работу с 'catch()', потому что он не делает того, что вы хотите. – martin

+0

Но если вы увидите этот пример: https://jsfiddle.net/ibrahimislam/ecLp6h1u. Он работает так, как ожидалось. – lbrahim

Смежные вопросы