ホームページ > 記事 > ウェブフロントエンド > JSONP 原則の詳細な解釈
以下のエディターは、JSONP 原則に基づいた分析を推奨しています。これが皆さんの参考になれば幸いです。編集者をフォローして見てみましょう
前書き
私が仕事を始めてから最初に取り組んだプロジェクトは、フロントエンドとバックエンドの分離です。フロントエンドの静的ファイルには独自のものがあります。独立したドメイン名を使用し、データはレンダリングやその他の操作のためにインターフェイスを通じて取得されます。
クロスドメインのメソッドについて詳しく説明する必要はありません。検索すればたくさんありますが、最も一般的に使用されるメソッドは jsonp と CORS です。 jsonp はフロントエンドに焦点を当てています。フロントエンドの Hack スキルはバックエンドよりも重要であり、サーバーをさらに構成する必要があります。
この記事では、jsonp の実装原理を分析します。
基本原則
基本原則は簡単に説明できます。img、script、link など、HTML ページにはクロスドメインの制限を受けないタグがいくつかあります。必要なデータを js ファイルに入れると、ブラウザーの同一オリジン制限を突破できます。
スクリプトタグを作成する
動的スクリプト要素については「高性能JavaScript」で説明されており、著者は次のように書いています:
1. 要素がページに追加されると、ファイルのダウンロードが開始されます。この手法の重要な点は、ダウンロードが開始されるたびに、ファイルのダウンロードと実行がページ上の他のプロセスをブロックしないことです。
2. 動的スクリプト ノードを使用してファイルをダウンロードする場合、返されたコードは通常、すぐに実行されます (Firefox と Oprea は例外で、以前のすべての動的スクリプト ノードの実行が完了するまで待機します)。スクリプト自体が実行されると、このメカニズムが実行されます。正常に動作します。
引用 1 は、JSONP リクエストを行うときにメインスレッドがブロックされないことを保証します。引用 2 は、JSONP コードがロード直後に実行されるときにエラーが発生しないことを保証します。
callback
GET リクエストを受信した後、サーバーは通常、コールバック パラメーターがあるかどうかを判断し、存在する場合は、返されたデータの外側にメソッド名と括弧を追加する必要があります。たとえば、次のリクエストを開始した場合:
http://www.a.com/getSomething?callback=jsonp0
サーバーは次のコンテンツを返します:
jsonp0({code:200,data:{}})
明らかに、これは動的にロードされた Script タグに含まれるコンテンツであるため、これは自己実行コードの一部です。このコードは、関数が呼び出される - jsonp0 のみです。
もちろん、実行がある場合は、最初に作成する必要があります。そうしないと、エラーが報告されます。この作成ステップは、呼び出す前に実行する必要があります。
具体的な実装は以下の通りです:
function jsonp (url, successCallback, errorCallback, completeCallback) { // 声明对象,需要将函数声明至全局作用域 window.jsonp0 = function (data) { successCallback(data); if (completeCallback) completeCallback(); } // 创建script标签,并将url后加上callback参数 var script = document.createElement('script') , url = url + (url.indexOf('?') == -1 ? '?' : '&') + 'callback=jsonp0' ; script.src = url; document.head.parentNode.insertBefore(script, document.head); // 等到script加载完毕以后,就会自己执行 }
以上で基本的にjsonpメソッドの中核部分が完成します。 この時点でjsonp0は宣言した関数であり、サーバーが正常に復帰するとjsonp0関数が実行されます。内部の successCallback コールバックも実行されます。
改善してください
実際の状況では、通常、同時に多くの jsonp リクエストが呼び出されます
では、jsonp0 はニーズを満たすことができるのに、なぜ jsonp1、jsonp2 などが追加されるのが頻繁に発生します。順番にコードはどうでしょうか?
これは、リクエストが非同期的に行われる可能性があるためです。初めてjsonpメソッドを実行するときは、window.jsonp0が関数Aになります。このとき、jsファイルが読み込まれます。jsが読み込まれていない場合は、再度jsonpメソッドが呼び出されます。機能B。次に、2 つの js がロードされた後、2 番目のコールバックが実行されます。
そのため、コールバックの名前で区別する必要があり、蓄積することでニーズを満たすことができます。
コードを変更します:
var jsonpCounter = 0; function jsonp (url, successCallback, errorCallback, completeCallback) { var jsId = 'jsonp' + jsonpCounter++; // 声明对象,需要将函数声明至全局作用域 window[jsId] = function (data) { successCallback(data); if (completeCallback) completeCallback(); clean(); } // 创建script标签,并将url后加上callback参数 var script = document.createElement('script') , url = url + (url.indexOf('?') == -1 ? '?' : '&') + 'callback=' + jsId ; script.src = url; document.head.parentNode.insertBefore(script, document.head); // 等到script加载完毕以后,就会自己执行 //在执行完我们这个方法以后,会有很多script标签出现在head之前,我们需要手动的删除掉他们。 function clean () { script.parentNode.removeChild(script); window[jsId] = function(){}; } }
蓄積とクリーニングを追加した後も、エラー コールバックという処理すべき重要な場所がまだ残っています。通常、jsonp をリクエストするとタイムアウトが設定され、この時間を超えるとタイムアウト例外がスローされます。
実装は次のとおりです:
var jsonpCounter = 0; function jsonp (url, successCallback, errorCallback, completeCallback, timeout) { // 略去上面写过的代码 var timeout = timeout || 10000 , timer ; if (timeout) { timer = setTimeout(function () { if (errorCallback) { errorCallback(new Error('timeout')); } clean(); }, timeout) } function clean () { script.parentNode.removeChild(script); window[jsId] = function(){}; if (timer) clearTimeout(timer); } }
このようにして、jsonp のすべての機能は基本的に完成し、残りは完全な jsonp メソッドとみなされるために互換性のある変更が必要になる場合があります。
参照
「高性能JavaScript」
npmでのjsonp実装、JSONP
上記は、皆さんのために私がまとめたものです。将来皆さんのお役に立てれば幸いです。
関連記事:
ReactNativeでReduxアーキテクチャを使用する方法
AngularでMathJaxを使用するとどのような問題が発生しますか?
以上がJSONP 原則の詳細な解釈の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。