postMessageはとても役に立ちます
15821 ワード
前言:この文章は皆さんと一緒にpostMessageをよく認識して、その互換性、対応するAPIの紹介、およびよくあるいくつかの使用シーンを含めて、同じ困惑している盆友たちに少し啓発して、この技術を使う必要がある同僚たちに少し助けてほしいです.
postMessageの定義
postMessageはhtml 5に導入するAPIであり、postMessage()方法は異なるソースからのスクリプトが非同期方式で有効な通信を行うことを可能にし、文書ドキュメント、マルチウィンドウ、ドメイン間メッセージ伝達を実現することができる.ウィンドウ間のデータ通信に用いることが多く、ドメイン間通信の有効な解決策となる.
PostMessageの互換性
下図はcaniuseで検索postMessage互換性の断面図であり、IEブラウザのサポート度が比較的低いことを除き、他のブラウザのサポート度は良好である.
postMessage APIの紹介
送信データ:
otherWindow
ウィンドウの1つの引用、例えばiframeのcontentWindow属性、windowを実行します.Openが返すウィンドウオブジェクト、または名前付きまたは数値インデックスのwindow.frames.
message
他のウィンドウに送信するデータは、[!構造化されたクローンアルゴリズム](Structural Clone Algorithm)(https://developer.mozilla.org/en-US/docs/DOM/The_structured_clone_algorithm)シーケンス化これは、自分でシーケンス化することなく、データオブジェクトをターゲットウィンドウに安全に転送できることを意味する.
targetOrigin
ウィンドウのorigin属性によりメッセージイベントを受信できるウィンドウを指定し、指定後はoriginの下のウィンドウに対応するのみメッセージを受信することができ、ワイルドカード「*」に設定すると任意のウィンドウに送信できることを示すが、通常はセキュリティ上の考慮では推奨されない.現在のウィンドウと同じソースのウィンドウに送信する場合は、[/]に設定します.
Transfer|オプション属性
メッセージと同時に送信*Transferable**オブジェクトの一連であり、これらのオブジェクトの所有権はメッセージの受信者に転送され、送信側は所有権を保有しない.
受信データ:messageイベントの発生を傍受する
eventオブジェクトの印刷結果の断面図は次のとおりです.
ここではeventオブジェクトの4つのプロパティに重点を置きます data:他のウィンドウから送信されたメッセージオブジェクトを指す. type:メッセージを送信するタイプを指す. source:メッセージを送信するウィンドウオブジェクトを指す. origin:メッセージを送信するウィンドウのソース を指す.
postMessageの使用シーン
シーン1ドメイン間通信(GETリクエストとPOSTリクエストを含む)
JSONPはGET要求のドメイン間問題を解決することができることはよく知られているが、POST要求のドメイン間問題を解決することはできない.postMessageでもいいですここではただ一つの例を挙げますが、参考までに、具体的なコードをどのように書くかは具体的なシーンで決めます.
親フォームはドメイン間iframeを作成し、情報を送信します.
サブフォームは情報を受信して処理します
シーン2 WebWorker
JavaScript言語は単一スレッドモデルを採用しており、通常、すべてのタスクは1つのスレッドで完了し、一度に1つのことしかできない.後のタスクは前のタスクが実行されてから実行を開始することができるが、この方法は複雑な時間の計算に遭遇すると、ブロックが発生し、アプリケーションの正常な実行を深刻に阻害する.Web Workerは、Webコンテンツがバックグラウンドスレッドでスクリプトを実行するための簡単な方法を提供し、スレッドはユーザーインタフェースに干渉することなくタスクを実行することができる.作成すると、workerは、その作成するJavaScriptコードにメッセージを送信し、メッセージを変更コードで指定されたイベントハンドラにパブリッシュすることができる.
1つのwokerは、1つのコンストラクション関数を使用してオブジェクトを作成し、名前付きJavaScriptファイルを実行する-このファイルはワークスレッドで実行するコードを含み、wokerは別のグローバルコンテキストで実行され、現在のwindowとは異なり、windowを使用して全局属性を取得することはできません.
いくつかの限界は同源スクリプトファイルのみをロードすることができ、DOMノード を直接操作することはできない. Workerスレッドでは を発行できます.ローカルファイルを読み取ることができず、ネットワークファイル のみをロードすることができる.もwindowオブジェクトのデフォルトの方法と属性を使用することはできませんが、webSocket、indexedDB、FireFoxOS専用のDアタスストアAPIなどのデータ格納メカニズムを含む多くのwindowオブジェクトの下のものを使用することができます.詳細については、Functions and classes available to workersを参照してください.
workersとプライマリ・スレッド間のデータ転送は、postMessage()メソッドを使用してそれぞれのメッセージを送信し、onmessageイベント処理関数を使用してメッセージに応答する(メッセージは
専用wokerの使用例:
Web Workerの使用シーンは、埋込データを収集するためのものであり、大量の複雑なデータ計算、複雑な画像処理、ビッグデータの処理に用いることができる.メインスレッドの正常な実行とページUIのレンダリングを阻害しないためである.
埋点データ収集下での使用:main.jsで収集するデータは、収集した情報をpostMessageでworkerに送信する.js、woker.jsでは関連演算と整理を行い、サーバ側に送信する.もちろん、Web Wokerを用いることなく、単一ページアプリケーションにおけるindexを通過する.htmlの中でiframeを作成してもページ間の切り替えを実現することができて、ページの滞在時間の長さなどのデータの採集、具体的な実現は私は詳しく話しません、興味のある学生はネット上で解決策を検索することができて、どんな疑問が私信を歓迎します~~~
シーン3 Service Worker
サービスWorkerの存在はブラウザコンソールのアプリケーションで確認できます
Service Workerは、Webアプリケーションがオフラインで格納される最適なソリューションです.Service WorkerとWeb Workerの同じ点は、従来のjsエンジンスレッド以外に、プライマリ・スレッドで処理するのに適さないビジネスを処理する新しいjsスレッドを開発することです.異なる点は、主に以下の点です. Web Workerは特定のページにサービスするが、サービスWorkerは登録インストール後に複数のページで を使用することができる. Service Workerはブラウザに常駐する、ページのクローズによって破棄されることはない.本質的には、バックグラウンドスレッドであり、アクティブに終了したり、ブラウザが回収したりしてこそ、このスレッドは終了します. ライフサイクル、呼び出し可能なAPIも異なる ServiceWorkerを使用してキャッシュを行い、jsを使用してブラウザのhttpリクエストをブロックし、キャッシュファイルを設定してオフラインウェブアプリケーションを作成することができます.サービスWorkerの概念についての紹介はここまでです~~、興味のある方は関連記事を探して勉強して、疑問のある方は私信を歓迎して私と検討してください~,ここで主にpostMessageの方法を使ってサービスWorkerとページ間の通信を行うことを紹介します.
ページからサービスWorkerへのメッセージの送信
注意する必要があるのは、このページがブラウザに直接投げ込まれた場合(fileプロトコルを使用している)、開くのは間違っています.nginxを使用してポートマッピングを行うか、nodeを使用してサーバーを構築して(httpプロトコルを使用して)このページにアクセスします(現在、閲覧器がfileプロトコルが開いているファイルにいくつかのサービスの制限をしているためだと推測しています.ポートマッピングのための私のnginxの構成も添付します.
nginxはポートマッピングに関する構成を行います.
実行された効果のスクリーンショット:
これでサービスWorkerと他のページとの通信が実現し、興味のある仲間が一緒にやってみることができます.もしあなたが間違ったことを報告したら、自分のコードをよくチェックしてください.
締めくくり
ええと、一苦労してやっとまとめましたが、文章は详しくないかもしれません.结局、一つの技术には多くの拡张と分岐分野があります.一つ一つ绍介するのは难しいです.私のブログを书くレベルも向上しなければなりません.研究や兴味があるか、文章に间违いがあることを発见した友达と私の交流を歓迎します.メールアドレス[email protected].
以前の文章.
vueでSockJSを用いてwebSocket通信を実現
表の表の頭を浮かべるように手を教えてあげます(table-header-fixed)
Expires,Last-Modified,Etagキャッシュメカニズム
転載先:https://juejin.im/post/5b8359f351882542ba1dcc31
postMessageの定義
postMessageはhtml 5に導入するAPIであり、postMessage()方法は異なるソースからのスクリプトが非同期方式で有効な通信を行うことを可能にし、文書ドキュメント、マルチウィンドウ、ドメイン間メッセージ伝達を実現することができる.ウィンドウ間のデータ通信に用いることが多く、ドメイン間通信の有効な解決策となる.
PostMessageの互換性
下図はcaniuseで検索postMessage互換性の断面図であり、IEブラウザのサポート度が比較的低いことを除き、他のブラウザのサポート度は良好である.
postMessage APIの紹介
送信データ:
otherWindow.postMessage(message, targetOrigin, [transfer]);
otherWindow
ウィンドウの1つの引用、例えばiframeのcontentWindow属性、windowを実行します.Openが返すウィンドウオブジェクト、または名前付きまたは数値インデックスのwindow.frames.
message
他のウィンドウに送信するデータは、[!構造化されたクローンアルゴリズム](Structural Clone Algorithm)(https://developer.mozilla.org/en-US/docs/DOM/The_structured_clone_algorithm)シーケンス化これは、自分でシーケンス化することなく、データオブジェクトをターゲットウィンドウに安全に転送できることを意味する.
targetOrigin
ウィンドウのorigin属性によりメッセージイベントを受信できるウィンドウを指定し、指定後はoriginの下のウィンドウに対応するのみメッセージを受信することができ、ワイルドカード「*」に設定すると任意のウィンドウに送信できることを示すが、通常はセキュリティ上の考慮では推奨されない.現在のウィンドウと同じソースのウィンドウに送信する場合は、[/]に設定します.
Transfer|オプション属性
メッセージと同時に送信*Transferable**オブジェクトの一連であり、これらのオブジェクトの所有権はメッセージの受信者に転送され、送信側は所有権を保有しない.
受信データ:messageイベントの発生を傍受する
window.addEventListener("message", receiveMessage, false) ;
function receiveMessage(event) {
var origin= event.origin;
console.log(event);
}
eventオブジェクトの印刷結果の断面図は次のとおりです.
ここではeventオブジェクトの4つのプロパティに重点を置きます
postMessageの使用シーン
シーン1ドメイン間通信(GETリクエストとPOSTリクエストを含む)
JSONPはGET要求のドメイン間問題を解決することができることはよく知られているが、POST要求のドメイン間問題を解決することはできない.postMessageでもいいですここではただ一つの例を挙げますが、参考までに、具体的なコードをどのように書くかは具体的なシーンで決めます.
親フォームはドメイン間iframeを作成し、情報を送信します.
"utf-8">
"X-UA-Compatible" content="IE=edge">
POST
type</span>=<span class="hljs-string">"text/JavaScript"</span>>
// sendPost postMessage moweide.gitcafe.io ,
//
<span class="hljs-keyword">function</span> <span class="hljs-function"><span class="hljs-title">sendPost</span></span>() {
// id otherPage iframe
var iframeW<span class="hljs-keyword">in</span> = document.getElementById(<span class="hljs-string">"otherPage"</span>).contentWindow;
//
iframeWin.postMessage(document.getElementById(<span class="hljs-string">"message"</span>).value,
<span class="hljs-string">'http://moweide.gitcafe.io'</span>);
}
//
window.addEventListener(<span class="hljs-string">"message"</span>, <span class="hljs-keyword">function</span>(event) {
console.log(event, event.data);
}, <span class="hljs-literal">false</span>);
type="button" value=" " onclick="sendPost()">
サブフォームは情報を受信して処理します
"utf-8">
"X-UA-Compatible" content="IE=edge">
POST Handler
"//code.jquery.com/jquery-1.11.0.min.js"</span>>
type</span>=<span class="hljs-string">"text/JavaScript"</span>>
window.addEventListener(<span class="hljs-string">"message"</span>, <span class="hljs-keyword">function</span>( event ) {
// post
var data = event.data;
$.ajax({
// url .
<span class="hljs-built_in">type</span>: <span class="hljs-string">'POST'</span>,
url: <span class="hljs-string">'http://moweide.gitcafe.io/getData'</span>,
data: <span class="hljs-string">"info="</span> + data,
dataType: <span class="hljs-string">"json"</span>
}).done(<span class="hljs-keyword">function</span>(res){
// postMessage
window.parent.postMessage(res, <span class="hljs-string">"*"</span>);
}).fail(<span class="hljs-keyword">function</span>(res){
// postMessage
window.parent.postMessage(res, <span class="hljs-string">"*"</span>);
});
}, <span class="hljs-literal">false</span>);
シーン2 WebWorker
JavaScript言語は単一スレッドモデルを採用しており、通常、すべてのタスクは1つのスレッドで完了し、一度に1つのことしかできない.後のタスクは前のタスクが実行されてから実行を開始することができるが、この方法は複雑な時間の計算に遭遇すると、ブロックが発生し、アプリケーションの正常な実行を深刻に阻害する.Web Workerは、Webコンテンツがバックグラウンドスレッドでスクリプトを実行するための簡単な方法を提供し、スレッドはユーザーインタフェースに干渉することなくタスクを実行することができる.作成すると、workerは、その作成するJavaScriptコードにメッセージを送信し、メッセージを変更コードで指定されたイベントハンドラにパブリッシュすることができる.
1つのwokerは、1つのコンストラクション関数を使用してオブジェクトを作成し、名前付きJavaScriptファイルを実行する-このファイルはワークスレッドで実行するコードを含み、wokerは別のグローバルコンテキストで実行され、現在のwindowとは異なり、windowを使用して全局属性を取得することはできません.
いくつかの限界
alert()
メソッドとconfirm()
メソッドは実行できませんが、XMLHttpRequestオブジェクトを使用してAJAXリクエストworkersとプライマリ・スレッド間のデータ転送は、postMessage()メソッドを使用してそれぞれのメッセージを送信し、onmessageイベント処理関数を使用してメッセージに応答する(メッセージは
Message
イベントのdata属性に含まれる).この過程でデータは共有されるのではなく複製される.wokerは専用workerと共有workerに分けられ、1つの専用workerが初めて生成するスクリプトで緊急に使用され、共有wokerは同時に複数のスクリプトで使用することができる.専用wokerの使用例:
// main.js
if(window.Worker) {
var myWorker = new Worker('http://xxx.com/worker.js');
//
first.onchange = function() {
myWorker.postMessage([first.value, second.value]);
console.log("Message posted to worker");
}
second.onchange = function() {
myWorker.postMessage([first.value,second.value]);
console.log('Message posted to worker');
}
// onmessage worker
myWorker.onmessage = function (e) {
var textContent = e.data;
console.log("message received from worker");
}
}
// worker.js
// selfduixiang,, , worker , importScripts()
onmessage = function(e) {
console.log("message received from main script");
var workerResult = "Result: " + (e.data[0] * e.data[1]);
console.log("posting message\back to main script");
postMessage(workerResult);
}
Web Workerの使用シーンは、埋込データを収集するためのものであり、大量の複雑なデータ計算、複雑な画像処理、ビッグデータの処理に用いることができる.メインスレッドの正常な実行とページUIのレンダリングを阻害しないためである.
埋点データ収集下での使用:main.jsで収集するデータは、収集した情報をpostMessageでworkerに送信する.js、woker.jsでは関連演算と整理を行い、サーバ側に送信する.もちろん、Web Wokerを用いることなく、単一ページアプリケーションにおけるindexを通過する.htmlの中でiframeを作成してもページ間の切り替えを実現することができて、ページの滞在時間の長さなどのデータの採集、具体的な実現は私は詳しく話しません、興味のある学生はネット上で解決策を検索することができて、どんな疑問が私信を歓迎します~~~
シーン3 Service Worker
サービスWorkerの存在はブラウザコンソールのアプリケーションで確認できます
Service Workerは、Webアプリケーションがオフラインで格納される最適なソリューションです.Service WorkerとWeb Workerの同じ点は、従来のjsエンジンスレッド以外に、プライマリ・スレッドで処理するのに適さないビジネスを処理する新しいjsスレッドを開発することです.異なる点は、主に以下の点です.
ページからサービスWorkerへのメッセージの送信
注意する必要があるのは、このページがブラウザに直接投げ込まれた場合(fileプロトコルを使用している)、開くのは間違っています.nginxを使用してポートマッピングを行うか、nodeを使用してサーバーを構築して(httpプロトコルを使用して)このページにアクセスします(現在、閲覧器がfileプロトコルが開いているファイルにいくつかのサービスの制限をしているためだと推測しています.ポートマッピングのための私のnginxの構成も添付します.
"utf-8">
"X-UA-Compatible" content="IE=edge">
Service Worker
"sw1.js"</span>>
"sw2.js"</span>>
type</span>=<span class="hljs-string">"text/JavaScript"</span>>
<span class="hljs-keyword">if</span>(<span class="hljs-string">'serviceWorker'</span> <span class="hljs-keyword">in</span> window.navigator) {
// scope Service Worker, Service Worker
navigator.serviceWorker.register(<span class="hljs-string">'./sw1.js'</span>, { scope:<span class="hljs-string">'./sw1'</span>})
.then(<span class="hljs-keyword">function</span>(reg) {
console.log(<span class="hljs-string">'success'</span>, reg);
<span class="hljs-built_in">return</span> new Promise((resolve, reject) => {
const interval = <span class="hljs-built_in">set</span>Interval(<span class="hljs-function"><span class="hljs-title">function</span></span>() {
<span class="hljs-keyword">if</span>(reg.active) {
clearInterval(interval);
resolve(reg.active);
}
}, 1000);
}).then(sw => {
sw.postMessage(<span class="hljs-string">"this message is from page to sw1"</span>);
})
})
navigator.serviceWorker.register(<span class="hljs-string">'./sw2.js'</span>, { scope:<span class="hljs-string">'./sw2'</span>})
.then(<span class="hljs-keyword">function</span>(reg) {
console.log(<span class="hljs-string">'success'</span>, reg);
<span class="hljs-built_in">return</span> new Promise((resolve, reject) => {
const interval = <span class="hljs-built_in">set</span>Interval(<span class="hljs-function"><span class="hljs-title">function</span></span>() {
<span class="hljs-keyword">if</span>(reg.active) {
clearInterval(interval);
resolve(reg.active);
}
}, 1000);
}).then(sw => {
sw.postMessage(<span class="hljs-string">"this message is from page to sw2"</span>);
})
});
navigator.serviceWorker.addEventListener(<span class="hljs-string">'message'</span>, <span class="hljs-keyword">function</span> (event) {
console.log(event.data);
// , DOM
document.getElementById(<span class="hljs-string">'showArea'</span>).value = event.data ;
});
}
// sw1.js
self.addEventListener("message", function(event) {
console.log("sw1.js " + event.data);
event.source.postMessage('this message is from sw1.js, to page');
});
// sw2.js
self.addEventListener("message", function(event) {
console.log("sw2.js " + event.data);
// event.source
event.source.postMessage('this message is from sw2.js, to page');
});
nginxはポートマッピングに関する構成を行います.
// nginx.conf
// nginx
// nginx conf.d .
// include
http {
# nginx
include conf.d/*.conf;
}
// testHtml.conf
server {
listen 9090;
server_name localhost;
location / {
root C:/Users/hzljie/Desktop/test/testb;
# ,
index test.html test.htm;
}
}
実行された効果のスクリーンショット:
これでサービスWorkerと他のページとの通信が実現し、興味のある仲間が一緒にやってみることができます.もしあなたが間違ったことを報告したら、自分のコードをよくチェックしてください.
締めくくり
ええと、一苦労してやっとまとめましたが、文章は详しくないかもしれません.结局、一つの技术には多くの拡张と分岐分野があります.一つ一つ绍介するのは难しいです.私のブログを书くレベルも向上しなければなりません.研究や兴味があるか、文章に间违いがあることを発见した友达と私の交流を歓迎します.メールアドレス[email protected].
以前の文章.
vueでSockJSを用いてwebSocket通信を実現
表の表の頭を浮かべるように手を教えてあげます(table-header-fixed)
Expires,Last-Modified,Etagキャッシュメカニズム
転載先:https://juejin.im/post/5b8359f351882542ba1dcc31