RxJs-beta12以降が必要です前の要求がまだ保留中のときは1300ms
になります(200ms
が必要です)。両方の結果が必要なときに受信されます。
publishReplay()
には有効な値が含まれていないため、何も出力せず、即座に完了しない(take(1)
)ので、HTTPリクエストを送信するソースに登録する必要がある(これは実際にrefCount()
で起こります)。
次に、2番目のサブスクライバも何も受信せず、publishReplay()
のオブザーバの配列に追加されます。すでにソース(refCount()
)に登録されており、応答を待っているため、別のサブスクリプションは作成されません。
あなたが描いている状況は起こるべきではないと思います。最終的に問題を示すデモを作成してください。
EDIT:
無効化項目および新鮮アイテム
次の例の両方を放出は、リンクされた例より少し異なる機能を示しています。キャッシュされたレスポンスが無効になっていると、それはとにかく放出され、新しい値も受け取られます。
- 1値:キャッシュされた値
- 2値:無効にキャッシュされた値が、その後、今からキャッシュされます新鮮な値を新しいこれは、加入者は、1つのまたは2つの値を受信します。
コードは、次のようになります。
let counter = 1;
const RECACHE_INTERVAL = 1000;
function mockDataFetch() {
return Observable.of(counter++)
.delay(200);
}
let source = Observable.defer(() => {
const now = (new Date()).getTime();
return mockDataFetch()
.map(response => {
return {
'timestamp': now,
'response': response,
};
});
});
let updateRequest = source
.publishReplay(1)
.refCount()
.concatMap(value => {
if (value.timestamp + RECACHE_INTERVAL > (new Date()).getTime()) {
return Observable.from([value.response, null]);
} else {
return Observable.of(value.response);
}
})
.takeWhile(value => value);
setTimeout(() => updateRequest.subscribe(val => console.log("Response 0:", val)), 0);
setTimeout(() => updateRequest.subscribe(val => console.log("Response 50:", val)), 50);
setTimeout(() => updateRequest.subscribe(val => console.log("Response 200:", val)), 200);
setTimeout(() => updateRequest.subscribe(val => console.log("Response 1200:", val)), 1200);
setTimeout(() => updateRequest.subscribe(val => console.log("Response 1300:", val)), 1300);
setTimeout(() => updateRequest.subscribe(val => console.log("Response 1500:", val)), 1500);
setTimeout(() => updateRequest.subscribe(val => console.log("Response 3500:", val)), 3500);
はライブデモを参照してください:https://jsbin.com/ketemi/2/edit?js,console
これは、次のような出力をコンソールに出力します。
Response 0: 1
Response 50: 1
Response 200: 1
Response 1200: 1
Response 1300: 1
Response 1200: 2
Response 1300: 2
Response 1500: 2
Response 3500: 2
Response 3500: 3
お知らせ1200
と受信1300
最初に古いキャッシュ値1
をすぐに新しい値2
の値を持つ別の値。
一方、2
はすでにキャッシュされており、有効であるため、1500
は新しい値のみを受け取りました。
おそらく最も混乱しているのは、なぜconcatMap().takeWhile()
ですか?これは、完全な通知を送信する前に新鮮なレスポンス(無効化されていない)が最後の値であることを確認する必要があり、そのための演算子が存在しない可能性があるからです(first()
もtakeWhile()
もこのユースケースに該当しません)。私たちは、HTTPリクエストからの新鮮な応答を待っていない間だけキャッシュされた値を放出したいときにさらに別のユースケースは、可能性がリフレッシュ
を待たずに、現在のアイテムを発する
。それが今無効だにもかかわらず、キャッシュされた値をだから1200
と1300
の両方が値1
を受け取ること
Response 0: 1
Response 50: 1
Response 200: 1
Response 1200: 1
Response 1300: 1
Response 1500: 2
Response 3500: 2
Response 3800: 3
お知らせ:https://jsbin.com/kebapu/2/edit?js,console
この例のプリントコンソールに:
let counter = 1;
const RECACHE_INTERVAL = 1000;
function mockDataFetch() {
return Observable.of(counter++)
.delay(200);
}
let source = Observable.defer(() => {
const now = (new Date()).getTime();
return mockDataFetch()
.map(response => {
return {
'timestamp': now,
'response': response,
};
});
});
let updateRequest = source
.publishReplay(1)
.refCount()
.concatMap((value, i) => {
if (i === 0) {
if (value.timestamp + RECACHE_INTERVAL > (new Date()).getTime()) { // is cached item valid?
return Observable.from([value.response, null]);
} else {
return Observable.of(value.response);
}
}
return Observable.of(null);
})
.takeWhile(value => value);
setTimeout(() => updateRequest.subscribe(val => console.log("Response 0:", val)), 0);
setTimeout(() => updateRequest.subscribe(val => console.log("Response 50:", val)), 50);
setTimeout(() => updateRequest.subscribe(val => console.log("Response 200:", val)), 200);
setTimeout(() => updateRequest.subscribe(val => console.log("Response 1200:", val)), 1200);
setTimeout(() => updateRequest.subscribe(val => console.log("Response 1300:", val)), 1300);
setTimeout(() => updateRequest.subscribe(val => console.log("Response 1500:", val)), 1500);
setTimeout(() => updateRequest.subscribe(val => console.log("Response 3500:", val)), 3500);
setTimeout(() => updateRequest.subscribe(val => console.log("Response 3800:", val)), 3800);
はライブデモを参照してください。 1200
の最初の呼び出しでは、応答を待たずに新しいHTTPリクエストが生成され、キャッシュされた値だけが送信されます。その後、1500
に新しい値がキャッシュされるので、再読み込みされます。同じことが3500
と3800
に適用されます。のサブスクライバは、ただちにnext
通知を受信しますが、complete
通知はHTTP要求の完了後に送信されることに注意してください。 complete
をnext
の直後に送ってしまえば、その使い捨て物を処分するチェーンを作るので、私たちは待つ必要があります。これはまた、HTTPリクエストをキャンセルする必要があります(これは間違いありません)。
提案していただきありがとうございます。これは非常に良いです。 2つの問題があります:チェーンから '.take(1)'演算子を削除する必要があります。そうでなければ、2回目のHTTP要求は行われません。 2番目の問題は、すべてのRECACHE_INTERVALではなく、RECACHE_INTERVALの後に別のsubsribe()が呼び出されたときに再キャッシュがトリガーされるようにすることです。 – Martin
@Martin私は、RECACHE_INTERVALの後に他の購読者が購読したときにのみリクエストが行われるように自分の回答を更新しました。これが役立つことを願って – Ashley