탭 또는 창 사이의 통신
추적을 남기지 않고 브라우저 (COS가 아닌 동일한 도메인의)에서 여러 탭 또는 창간에 통신하는 방법을 찾고있었습니다. 몇 가지 해결책이있었습니다.
첫 번째는 아마도 최악의 해결책 일 것입니다. 현재 창에서 창을 열어야하며 창을 열어 둔 상태에서만 통신 할 수 있습니다. 임의의 창에서 페이지를 다시로드하면 통신이 끊어졌을 가능성이 큽니다.
postMessage를 사용하는 두 번째 접근법은 아마도 원본 간 통신을 가능하게하지만 첫 번째 접근법과 동일한 문제를 겪습니다. 창 개체를 유지해야합니다.
세 번째 방법은 쿠키를 사용하여 브라우저에 일부 데이터를 저장하는 것입니다. 동일한 도메인의 모든 창에 메시지를 보내는 것처럼 보일 수 있지만 문제는 모든 탭이 이미 "메시지"를 읽었는지 여부를 알 수 없다는 것입니다 청소. 쿠키를 주기적으로 읽으려면 일종의 시간 초과를 구현해야합니다. 또한 최대 쿠키 길이 (4KB)로 제한됩니다.
localStorage를 사용하는 네 번째 솔루션은 쿠키의 한계를 극복하는 것처럼 보였으며 이벤트를 사용하여들을 수도 있습니다. 사용 방법은 허용 된 답변에 설명되어 있습니다.
2018 편집 : 허용 된 답변은 여전히 작동하지만 최신 브라우저에는 BroadcastChannel을 사용하는 최신 솔루션이 있습니다. BroadcastChannel을 사용하여 탭간에 메시지를 쉽게 전송하는 방법을 설명하는 간단한 예는 다른 답변을 참조하십시오.
2018 편집 :이 목적으로 BroadcastChannel을 더 잘 사용할 수 있습니다. 아래 다른 답변을 참조하십시오. 그러나 탭 간 통신에 여전히 로컬 저장소를 사용하려면 다음과 같이하십시오.
탭이 다른 탭으로 메시지를 보낼 때 알림을 받으려면 'storage'이벤트를 바인딩하면됩니다. 모든 탭에서 다음을 수행하십시오.
$(window).on('storage', message_receive);
message_receive
다른 탭에서 localStorage 값을 설정할 때마다 함수 가 호출됩니다. 이벤트 리스너에는 localStorage로 새로 설정된 데이터도 포함되므로 localStorage 객체 자체를 구문 분석 할 필요조차 없습니다. 트레이스를 효과적으로 정리하기 위해 설정 직후에 값을 재설정 할 수 있기 때문에 매우 편리합니다. 메시징 기능은 다음과 같습니다.
// use local storage for messaging. Set message in local storage and clear it right away
// This is a safe way how to communicate with other tabs while not leaving any traces
//
function message_broadcast(message)
{
localStorage.setItem('message',JSON.stringify(message));
localStorage.removeItem('message');
}
// receive message
//
function message_receive(ev)
{
if (ev.originalEvent.key!='message') return; // ignore other keys
var message=JSON.parse(ev.originalEvent.newValue);
if (!message) return; // ignore empty msg or msg reset
// here you act on messages.
// you can send objects like { 'command': 'doit', 'data': 'abcd' }
if (message.command == 'doit') alert(message.data);
// etc.
}
이제 탭이 onstorage 이벤트에서 바인드되고이 두 기능이 구현되면 다음과 같이 다른 탭 호출로 메시지를 브로드 캐스트 할 수 있습니다.
message_broadcast({'command':'reset'})
정확히 동일한 메시지를 두 번 보내는 것은 한 번만 전파되므로 메시지를 반복해야하는 경우 다음과 같은 고유 식별자를 추가하십시오.
message_broadcast({'command':'reset', 'uid': (new Date).getTime()+Math.random()})
또한 메시지를 브로드 캐스트하는 현재 탭은 실제로 메시지를 수신하지 않고 동일한 도메인의 다른 탭이나 창만 수신한다는 점을 기억하십시오.
removeItem () 이전에 setItem () 호출 직후에 사용자가 다른 웹 페이지를로드하거나 탭을 닫으면 어떻게되는지 물어볼 수 있습니다. 글쎄, 내 자신의 테스트에서 브라우저는 전체 기능 message_broadcast()
이 완료 될 때까지 언로드를 보류합니다 . 나는 매우 긴 for () 사이클을 넣는 것을 테스트했지만 사이클이 끝나기를 닫기 전에 여전히 기다렸다. 사용자가 그 사이에서 탭을 죽이면 브라우저에 메시지를 디스크에 저장할 시간이 충분하지 않으므로이 방법은 흔적없이 메시지를 보내는 안전한 방법과 같습니다. 의견 환영합니다.
이 목적을 위해 현대적인 API가 있습니다- 방송 채널
다음과 같이 쉽습니다.
var bc = new BroadcastChannel('test_channel');
bc.postMessage('This is a test message.'); /* send */
bc.onmessage = function (ev) { console.log(ev); } /* receive */
메시지가 단지 DOMString 일 필요는 없으며, 모든 종류의 객체가 전송 될 수 있습니다.
Probably, apart from API cleanness, it is the main benefit of this API - no object stringification.
Currently supported only in Chrome and Firefox, but you can find a polyfill that uses localStorage.
For those searching for a solution not based on jQuery, this is a plain JavaScript version of the solution provided by Thomas M:
window.addEventListener("storage", message_receive);
function message_broadcast(message) {
localStorage.setItem('message',JSON.stringify(message));
}
function message_receive(ev) {
if (ev.key == 'message') {
var message=JSON.parse(ev.newValue);
}
}
Checkout AcrossTabs - Easy communication between cross-origin browser tabs. It uses a combination of postMessage and sessionStorage API to make communication much easier and reliable.
There are different approaches and each one has its own advantages and disadvantages. Lets discuss each:
-
Pros:
- Web storage can be viewed simplistically as an improvement on cookies, providing much greater storage capacity. If you look at the Mozilla source code we can see that 5120KB (5MB which equals 2.5 Million chars on Chrome) is the default storage size for an entire domain. This gives you considerably more space to work with than a typical 4KB cookie.
- The data is not sent back to the server for every HTTP request (HTML, images, JavaScript, CSS, etc) - reducing the amount of traffic between client and server.
- The data stored in localStorage persists until explicitly deleted. Changes made are saved and available for all current and future visits to the site.
Cons:
- It works on same-origin policy. So, data stored will only be able available on the same origin.
-
Pros:
- Compared to others, there's nothing AFAIK.
Cons:
- The 4K limit is for the entire cookie, including name, value, expiry date etc. To support most browsers, keep the name under 4000 bytes, and the overall cookie size under 4093 bytes.
The data is sent back to the server for every HTTP request (HTML, images, JavaScript, CSS, etc) - increasing the amount of traffic between client and server.
Typically, the following are allowed:
- 300 cookies in total
- 4096 bytes per cookie
- 20 cookies per domain
- 81920 bytes per domain(Given 20 cookies of max size 4096 = 81920 bytes.)
-
Pros:
- It is similar to
localStorage
. - Changes are only available per window (or tab in browsers like Chrome and Firefox). Changes made are saved and available for the current page, as well as future visits to the site on the same window. Once the window is closed, the storage is deleted
Cons:
- The data is available only inside the window/tab in which it was set.
- The data is not persistent i.e. it will be lost once the window/tab is closed.
- Like
localStorage
, tt works on same-origin policy. So, data stored will only be able available on the same origin.
- It is similar to
-
Pros:
- Safely enables cross-origin communication.
- As a data point, the WebKit implementation (used by Safari and Chrome) doesn't currently enforce any limits (other than those imposed by running out of memory).
Cons:
- Need to open a window from the current window and then can communicate only as long as you keep the windows open.
- Security concerns - Sending strings via postMessage is that you will pick up other postMessage events published by other JavaScript plugins, so be sure to implement a
targetOrigin
and a sanity check for the data being passed on to the messages listener.
A combination of PostMessage + SessionStorage
Using postMessage to communicate between multiple tabs and at the same time using sessionStorage in all the newly opened tabs/windows to persist data being passed. Data will be persisted as long as the tabs/windows remain opened. So, even if the opener tab/window gets closed, the opened tabs/windows will have the entire data even after getting refreshed.
I have written a JavaScript library for this, named AcrossTabs which uses postMessage API to communicate between cross-origin tabs/windows and sessionStorage to persist the opened tabs/windows identity as long as they live.
Another method that people should consider using is Shared Workers. I know it's a cutting edge concept, but you can create a relay on a Shared Worker that is MUCH faster than localstorage, and doesn't require a relationship between the parent/child window, as long as you're on the same origin.
See my answer here for some discussion I made about this.
There's a tiny open-source component to sync/communicate between tabs/windows of the same origin (disclaimer - I'm one of the contributors!) based around localStorage
.
TabUtils.BroadcastMessageToAllTabs("eventName", eventDataString);
TabUtils.OnBroadcastMessage("eventName", function (eventDataString) {
DoSomething();
});
TabUtils.CallOnce("lockname", function () {
alert("I run only once across multiple tabs");
});
https://github.com/jitbit/TabUtils
P.S. I took the liberty to recommend it here since most of the "lock/mutex/sync" components fail on websocket connections when events happen almost simultaneously
I created a module that works equal to the official Broadcastchannel but has fallbacks based on localstorage, indexeddb and unix-sockets. This makes sure it always works even with Webworkers or NodeJS. See pubkey:BroadcastChannel
I've created a library sysend.js, it's very small, you can check its source code. The library don't have any external dependencies.
You can use it for communication between tabs/windows in same browser and domain. The library use BroadcastChannel, if supported, or storage event from localStorage.
API is very simple:
sysend.on('foo', function(message) {
console.log(message);
});
sysend.broadcast('foo', {message: 'Hello'});
sysend.broadcast('foo', "hello");
sysend.broadcast('foo'); // empty notification
when your brower support BroadcastChannel it sent literal object (but it's in fact auto-serialized by browser) and if not it's serialized to JSON first and deserialized on other end.
Recent version also have helper API to create proxy for Cross-Domain communication. (it require single html file on target domain).
Here is demo.
EDIT:
New version also support Cross-Domain communication, if you include special proxy.html
file on target domain and call proxy
function from source domain:
sysend.proxy('https://target.com');
(proxy.html it's very simple html file, that only have one script tag with the library).
If you want two way communication you need to do the same on target.com
domain.
NOTE: If you will implement same functionality using localStorage, there is issue in IE. Storage event is sent to the same window, which triggered the event and for other browsers it's only invoked for other tabs/windows.
I wrote an article on this on my blog: http://www.ebenmonney.com/blog/how-to-implement-remember-me-functionality-using-token-based-authentication-and-localstorage-in-a-web-application .
Using a library I created storageManager
you can achieve this as follows:
storageManager.savePermanentData('data', 'key'): //saves permanent data
storageManager.saveSyncedSessionData('data', 'key'); //saves session data to all opened tabs
storageManager.saveSessionData('data', 'key'); //saves session data to current tab only
storageManager.getData('key'); //retrieves data
There are other convenient methods as well to handle other scenarios as well
참고URL : https://stackoverflow.com/questions/28230845/communication-between-tabs-or-windows
'Programing' 카테고리의 다른 글
Python에서 JSON을 직렬화 할 때 "TypeError : (정수)를 JSON 직렬화 할 수 없습니다"? (0) | 2020.06.24 |
---|---|
rm이 파일을 찾지 못했다고보고하지 못하게하는 방법은 무엇입니까? (0) | 2020.06.24 |
존재하지 않는 경우 PostgreSQL 테이블 생성 (0) | 2020.06.24 |
argparse 모듈 인수없이 옵션을 추가하는 방법은 무엇입니까? (0) | 2020.06.24 |
Android Studio에서 build.gradle에 외부 프로젝트 추가 (0) | 2020.06.24 |