この記事は主に 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実装
関連する推奨事項:
以上がJSONP原則に基づいた詳細な説明の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。