RxJは、内部で観察可能なエラー(Ajaxリクエスト)が発生すると、クリックイベントのリッスンを停止します。イベントリスナーをボタンクリックイベントにフックしたままにして、内部のajaxエラーを適切に処理する方法を見つけようとしています。
これが私のサンプルコードとplunkrへのリンクです
var input = $("#testBtn");
var test = Rx.Observable.fromEvent(input,'click');
var testAjax = function() {
return Rx.Observable.range(0,3).then(function(x){
if(x==2)throw "RAWR"; //Simulating a promise error.
return x;
});
}
test.map(function(){
return Rx.Observable.when(testAjax());
})
.switchLatest()
.subscribe(
function (x) {
console.log('Next: ', x);
},
function (err) {
console.log('Error: ' + err);
},
function () {
console.log('Completed');
});
catch
演算子(またはcatchException
エイリアス)を使用して、オブザーバブルで発生するエラーをキャッチして処理し、サブスクライバーにエラーが通知されないようにすることができます。
エラーを無視する:
return Rx.Observable
.when(testAjax())
.catch(Rx.Observable.empty()); // continues with an empty obs after error.
エラーの処理:
var empty = Rx.Observable.return('default value');
return Rx.Observable
.when(testAjax())
.catch(function (error) {
console.log('error:', error);
return empty;
});
これ(およびonErrorResumeNext
)がどのように機能するかを解釈する私自身の問題に遭遇しました。私が遭遇した苦労は、キャッチ(またはresume next)がどのコンテキストに適用されたかでした。私にとって意味のある簡単な口語訳は次のとおりです。
オブザーバブルのストリーム(またはオブザーバブル)が与えられると、
catch
(またはonErrorResumeNext
)はエラーを消費し、元のストリームを継続するために1つ以上のオブザーバブルを提供できるようにします。
重要なポイントは、元のソースが中断され、catch
/onErrorResumeNext
関数で指定したオブザーバブルに置き換えられることです。これは、次のようなものがある場合を意味します。
var src = Rx.Observable
.interval(500)
.take(10)
.select(function(x) {
if (x == 5) {
return Rx.Observable.throw('Simulated Failure');
}
return Rx.Observable.return(x * 2);
})
次に、.catch(Rx.Observable.return('N/A'))
または.onErrorResumeNext(Rx.Observable.return('N/A'))
を追加すると、実際にはストリームが継続されるだけでなく(interval
によって供給されます)、最終的な監視対象(N/A
)でストリームが終了します。
代わりに、障害を適切に処理して元のストリームを続行する場合は、.select(function(x) { return x.catch(Rx.Observable.return('N/A')); })
のようなものにする必要があります。これで、ストリームは、キャッチされたデフォルトで失敗したストリーム内の監視可能な要素を置き換えてから、既存のソースストリームを続行します。
var src = Rx.Observable
.interval(500)
.take(10)
.select(function(x) {
if (x == 5) {
return Rx.Observable.throw('Simulated Failure');
}
return Rx.Observable.return(x * 2);
})
//.catch(Rx.Observable.return('N/A'))
//.onErrorResumeNext(Rx.Observable.return('N/A'))
.select(function(x) { return x.catch(Rx.Observable.return('N/A')); })
.selectMany(function(x) { return x; });
var sub = src.subscribe(
function (x) { console.log(x); },
function (x) { console.log(x); },
function () { console.log('DONE'); }
);
// OUTPUT:
// 0
// 2
// 4
// 6
// 8
// N/A
// 12
// 14
// 16
// 18
// DONE
これが JSFiddle で、これが実際に動作していることを示しています。
受け入れられた答えを試した後、私はまだ少し混乱していたので、これが私のために働いた結果でした。これは私が持っていたものです:
Rx.Observable.fromEvent(emitter, events.SUBMIT_EVENT)
.flatMapFirst(email=>{
return $.ajax({
method: "POST",
url: '/email',
data: {
email: email
},
}).promise()
})
.subscribe(response=>{
if (response) {
//do your success thing here
}
},
error =>{
//do your error thing
}
)
サーバーがエラーを返したとき(ユーザーがすでに電子メールを入力したときなど)、ユーザーの電子メールフォームの送信を再度聞くことができませんでした。これは私のために働いたものです:
Rx.Observable.fromEvent(emitter, events.SUBMIT_EVENT)
.flatMapFirst(email=>{
return $.ajax({
method: "POST",
url: '/email',
data: {
email: email
},
}).promise()
})
.doOnError(error=> {
//do your error thing here
})
.retry()
.subscribe(response=>{
if (response) {
//do your success thing here
}
})