ホームページ >ウェブフロントエンド >jsチュートリアル >キャッシュFETCED AJAXリクエストはローカルにリクエストします。フェッチAPIをラップします
この記事は、招待された著者ピーター・ベンツソンによって書かれました。 SitePointの特別ゲスト投稿は、JavaScriptコミュニティの有名な作家やスピーカーから素晴らしいコンテンツを提供するように設計されています
この記事では、フェッチされたリクエストのローカルキャッシュを実装する方法を示しているため、セッションストアから繰り返し実行されると読み取られます。これの利点は、キャッシュするすべてのリソースのカスタムコードを記述する必要がないことです。
次のJavaScriptパーティーを披露し、約束、最先端のAPI、およびローカルストレージを処理するためのさまざまなスキルを披露したい場合は、読み続けてください。
cachedFetch
標準の呼び出しをカプセル化します。これは、コンテンツの種類とURLに基づいて応答を自動的にキャッシュでき、キャッシュメカニズムを普遍的にします。 fetch
cachedFetch
fetch?https://www.php.cn/link/b751ea087892ebeca363034301f45c69フェッチ機能に対する主要なブラウザーのサポートに関するウェブサイトのデータ。
すべてのブラウザが完全に実装されているわけではない場合、GithubのFetch PolyFillを使用できます(一日中何もしていない場合は、ここにはフェッチ標準仕様があります)。単純な代替品
<code class="language-javascript">let origin = null; fetch('https://httpbin.org/get') .then(r => r.json()) .then(information => { origin = information.origin; // 您的客户端IP }); // 需要延迟以确保fetch已完成 setTimeout(() => { console.log('您的来源是 ' + origin); }, 3000);</code>CODEPEN例
これは、キャッシュされたデータを保持するためのグローバル変数にのみ依存します。直接的な問題は、ページをリロードしたり、新しいページに移動したりすると、キャッシュされたデータが消えることです。
その欠点を分析する前に、最初の簡単なソリューションをアップグレードしましょう。
<code class="language-javascript">fetch('https://httpbin.org/get') .then(r => r.json()) .then(info => { sessionStorage.setItem('information', JSON.stringify(info)); }); // 需要延迟以确保fetch已完成 setTimeout(() => { let info = JSON.parse(sessionStorage.getItem('information')); console.log('您的来源是 ' + info.origin); }, 3000);</code>CODEPEN例
最初の直接的な問題は、フェッチが約束に基づいていることです。つまり、いつ行われるかを判断できないため、確実性のために、約束が除いてその実行に依存してはなりません。
2番目の問題は、このソリューションが特定のURLと特定のキャッシュデータスニペットに非常に固有であることです(この例の重要な情報)。私たちが望むのは、ユニバーサルURLベースのソリューションです。
フェッチを返すラッパーの周りにラッパーを作成しましょう。それを呼び出すコードは、結果がネットワークからであるかローカルキャッシュからであるかを気にしないかもしれません。
それで、あなたがこれを行うのに使用していたと想像してください:
<code class="language-javascript">let origin = null; fetch('https://httpbin.org/get') .then(r => r.json()) .then(information => { origin = information.origin; // 您的客户端IP }); // 需要延迟以确保fetch已完成 setTimeout(() => { console.log('您的来源是 ' + origin); }, 3000);</code>CODEPEN例
これで、ネットワーク呼び出しを複製できるように、ローカルキャッシュの恩恵を受けることができます。 cachedfetchと呼んでみましょう。そうすれば、コードは次のようになります。
最初に実行されたとき、ネットワーク上で要求を解析し、結果をキャッシュに保存する必要があります。 2回目は、ローカルストレージから直接抽出する必要があります。
<code class="language-javascript">fetch('https://httpbin.org/get') .then(r => r.json()) .then(info => { sessionStorage.setItem('information', JSON.stringify(info)); }); // 需要延迟以确保fetch已完成 setTimeout(() => { let info = JSON.parse(sessionStorage.getItem('information')); console.log('您的来源是 ' + info.origin); }, 3000);</code>フェッチ機能をラップする単純なコードから始めましょう:
CODEPEN例
<code class="language-javascript">fetch('https://httpbin.org/get') .then(r => r.json()) .then(issues => { console.log('您的来源是 ' + info.origin); });</code>
これは機能しますが、もちろん機能しません。最初に抽出されたデータのストレージを実装しましょう。
CODEPEN例<code class="language-javascript">cachedFetch('https://httpbin.org/get') .then(r => r.json()) .then(info => { console.log('您的来源是 ' + info.origin); });</code>Fetchによって返された最初の約束は、実際にGet Requestを実行し続けます。 CORS(クロスオリジンリソース共有)に問題がある場合、.text()、.json()、または.blob()メソッドは機能しません。
最も興味深い機能は、最初の約束によって返された応答オブジェクトをクローンする必要があることです。そうでない場合、私たちは自分自身を挿入し、約束のエンドユーザーが.json()を呼び出すようにしようとするとき、彼らはこのエラーを取得します:
注意すべきもう1つのことは、応答タイプの慎重な処理です。ステータスコードが200
の場合のみ、コンテンツタイプがアプリケーション/jsonまたはテキスト/*である場合にのみ回答を保存します。これは、SessionStorageがテキストのみを保存できるためです。以下は、それを使用する方法の例です。 これまでのこのソリューションについての巧妙なことは、JSON
および<code class="language-javascript">const cachedFetch = (url, options) => { return fetch(url, options); };</code>HTMLリクエストを妨害することなく機能することです。それが画像である場合、それはセッションストレージに保存しようとはしません。
2回目の実装 - 実際のリターンキャッシュがヒット したがって、最初の実装は、リクエストの応答を保存する責任のみを担当します。ただし、CachedFetchを2回目に呼び出すと、SessionStorage
から何も取得しようとはしません。私たちがする必要があるのは、約束を返すことであり、約束は応答オブジェクトを解析する必要があります。非常に基本的な実装から始めましょう:
<code class="language-javascript">const cachedFetch = (url, options) => { // 使用URL作为sessionStorage的缓存键 let cacheKey = url; return fetch(url, options).then(response => { // 让我们只在内容类型为JSON或非二进制内容时存储在缓存中 let ct = response.headers.get('Content-Type'); if (ct && (ct.match(/application\/json/i) || ct.match(/text\//i))) { // 有一个.json()而不是.text(),但我们将它存储在sessionStorage中作为字符串。 // 如果我们不克隆响应,它将在返回时被使用。这样我们就可以不干扰。 response.clone().text().then(content => { sessionStorage.setItem(cacheKey, content); }); } return response; }); };</code>
CODEPEN例
実際にどのように機能するかを確認するには、このコードのCodepenを開き、開発者ツールでブラウザの[ネットワーク]タブを開きます。実行ボタンを数回押し(Codepenの右上隅)、画像のみがネットワーク上で繰り返し要求していることがわかります。
このソリューションの賢さの1つは、「コールバックパスタ」の欠如です。 sessionstorage.getItemコールは同期(つまり、ブロック)であるため、「ローカルストレージでは」と対処する必要はありません。また、コンテンツがある場合にのみ、キャッシュされた結果を返します。そうでない場合、IFステートメントは通常のコードのみを実行し続けます。3番目の実装 - 有効期限はどうですか?
より良い解決策は、
ユーザーを制御することです。 (この場合、ユーザーはcachedfetch関数を使用するWeb開発者です)。サーバー側のmemcachedまたはredisストレージと同様に、キャッシュする時間を指定する寿命を設定できます。 たとえば、
Python(Flaskを使用):
<code class="language-javascript">let origin = null; fetch('https://httpbin.org/get') .then(r => r.json()) .then(information => { origin = information.origin; // 您的客户端IP }); // 需要延迟以确保fetch已完成 setTimeout(() => { console.log('您的来源是 ' + origin); }, 3000);</code>今、SessionStorageもLocalStorageもこの機能を組み込んでいないため、手動で実装する必要があります。これは、保存された時間のタイムスタンプを常にログに記録し、それを使用して可能なキャッシュヒットを比較することで行います。
しかし、これを行う前にそれはどのように見えますか?たとえば、
<code class="language-javascript">fetch('https://httpbin.org/get') .then(r => r.json()) .then(info => { sessionStorage.setItem('information', JSON.stringify(info)); }); // 需要延迟以确保fetch已完成 setTimeout(() => { let info = JSON.parse(sessionStorage.getItem('information')); console.log('您的来源是 ' + info.origin); }, 3000);</code>追加する重要な新しいことは、応答データを保存するたびに、
を保存したときに記録することです。ただし、SessionStorageの代わりにLocalStorageのより信頼性の高いストレージに切り替えることもできます。カスタムの期限切れのコードにより、永続的なローカルストレージで非常に古いキャッシュヒットが得られないようにします。 これが私たちの究極の実用的なソリューションです:
CODEPEN例<code class="language-javascript">fetch('https://httpbin.org/get') .then(r => r.json()) .then(issues => { console.log('您的来源是 ' + info.origin); });</code>これらのWeb APIの過剰アクセスを避けるだけでなく、最良の部分は、LocalStorageが従属ネットワークよりもはるかに高速であることです。 LocalStorageとXHR:
では、どのようにしてソリューションをさらに改善するのでしょうか?
ここでの実装は、非テキストコンテンツ(画像など)をキャッシュしませんが、キャッシュしない理由はありません。もっとコードが必要です。特に、BLOBに関する詳細情報を保存したい場合があります。各応答は基本的にブロブです。テキストとJSONの場合、それは単なる文字列です。文字列自体から推測できるため、タイプとサイズは重要ではありません。バイナリ含有量の場合、BLOBはArrayBufferに変換する必要があります。
好奇心が強い人々のために、画像をサポートする実装拡張機能を表示するには、このCodepenを確認してください:[https://www.php.cn/link/946af3555203afdb63e571b873e419f6]。ハッシュキャッシュキーを使用します
この問題の解決策は、この巧妙なアルゴリズムを使用することです。これは安全かつ高速と見なされます。
これが好きなら、このCodepen:[https://www.php.cn/link/946af3555203afdb63e571b873e419f6]をチェックしてください。 Webコンソールのストレージを確認すると、557027443に似たキーが表示されます。
<code class="language-javascript">let origin = null; fetch('https://httpbin.org/get') .then(r => r.json()) .then(information => { origin = information.origin; // 您的客户端IP }); // 需要延迟以确保fetch已完成 setTimeout(() => { console.log('您的来源是 ' + origin); }, 3000);</code>
結論
最後のことは、このプロトタイプの自然な拡張、つまり、記事を超えて、テストとreadmesを使用して実際の特定のプロジェクトに移動し、NPMで公開することかもしれませんが、後で言われるべきです!
キャッシュされた抽出されたajax要求(FAQ)に関する
FAQフェッチAPIはキャッシュでどのように動作しますか?
Fetch APIには、いくつかのキャッシュモードが提供されます。 「デフォルト」は、標準のHTTPキャッシングルールに従います。 「ストアなし」はキャッシュを完全にバイパスします。 「リロード」はキャッシュされたデータを無視し、新しいリクエストを送信します。 「No-Cache」は、キャッシュバージョンを使用する前にサーバーを使用してデータを確認します。 「Force-Cache」は、新鮮さに関係なくキャッシュデータを使用します。 「キャッシュされていない場合」は、キャッシュデータが利用可能な場合にのみ使用しますが、それ以外の場合は失敗します。
Ajax設定でCache属性を設定することにより、Ajaxリクエストにキャッシュを実装できます。 Trueに設定すると、ブラウザが応答をキャッシュできます。または、フェッチAPIのキャッシュオプションを使用して、キャッシュの動作をよりよく制御できます。
Ajaxリクエストでのキャッシュを防ぐために、Ajax設定のキャッシュプロパティをFalseに設定できます。これにより、ブラウザは応答をキャッシュに保存しないようにします。または、フェッチAPIの「ストアなし」キャッシュオプションを使用して、キャッシュを完全にバイパスすることもできます。
AjaxとFetch APIの両方がキャッシュメカニズムを提供しますが、Fetch APIはより柔軟性と制御を提供します。 Ajaxのキャッシュプロパティは、キャッシュを許可または許可しない単純なブール値です。一方、Fetch APIのキャッシュオプションを使用すると、リクエストがキャッシュと対話する方法を指定して、より詳細な制御を可能にします。
キャッシュは、Webアプリケーションのパフォーマンスを大幅に改善できます。サーバーの応答のコピーを保存することにより、ブラウザは同じリクエストを再度行う必要はありません。これにより、サーバーの負荷が削減され、Webページの読み込み時間が高速化されます。ただし、ユーザーが最新のコンテンツを確認するために、キャッシュを正しく管理する必要があります。
はい、各リクエストのAJAX設定にキャッシュ属性を設定することにより、単一のAJAX要求のキャッシュ動作を制御できます。これにより、ブラウザが応答をキャッシュするかどうかを指定できます。
キャッシュAJAXリクエストのベストプラクティスは何ですか?
以上がキャッシュFETCED AJAXリクエストはローカルにリクエストします。フェッチAPIをラップしますの詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。