source

탭 또는 창 간의 통신

bestscript 2023. 1. 26. 09:15

탭 또는 창 간의 통신

흔적을 남기지 않고 브라우저(CORS가 아닌 같은 도메인)에서 여러 탭이나 창을 주고받는 방법을 찾고 있었습니다.몇 가지 솔루션이 있었습니다.

  1. 개체 사용
  2. 포스트 메시지
  3. 쿠키
  4. local 스토리지

첫 번째 방법은 아마도 최악의 해결책일 것입니다.현재 창에서 창을 열고 창을 열어 두어야만 통신할 수 있습니다.어느 하나의 창에서 페이지를 새로고침하면 대부분의 경우 통신이 끊어집니다.

post Message를 사용하는 두 번째 접근법은 아마도 크로스 오리진 통신을 활성화하지만 첫 번째 접근법과 동일한 문제를 겪습니다.창 개체를 유지 관리해야 합니다.

세 번째 방법은 쿠키를 사용하여 브라우저에 일부 데이터를 저장하는 것입니다.이러한 데이터는 같은 도메인의 모든 창에 메시지를 보내는 것처럼 보일 수 있지만 문제는 정리하기 전에 모든 탭이 이미 "메시지"를 읽었는지 여부를 알 수 없다는 것입니다.쿠키를 정기적으로 읽으려면 일종의 타임아웃을 실행해야 합니다.또한 쿠키의 최대 길이인 4KB로 제한됩니다.

네 번째 솔루션은 localStorage를 사용하여 쿠키의 한계를 극복하고 이벤트를 청취할 수도 있습니다.사용 방법은 승인된 답변에 설명되어 있습니다.

2018년에도 승인된 답변은 여전히 유효하지만, 최신 브라우저용 새로운 솔루션인 Broadcast Channel이 있습니다.브로드캐스트채널을 사용하여 탭 간에 메시지를 쉽게 전송하는 방법에 대한 간단한 예는 다른 답변을 참조하십시오.

이 경우 브로드캐스트채널을 사용하는 것이 좋습니다.아래의 다른 답변을 참조하십시오.그러나 탭 간 통신에 로컬 스토리지를 사용하는 경우에는 다음과 같이 하십시오.

탭이 다른 탭으로 메시지를 보낼 때 알림을 받으려면 '스토리지' 이벤트에 바인딩하기만 하면 됩니다.모든 탭에서 다음을 수행합니다.

$(window).on('storage', message_receive);

★★message_receivelocalStorage를 선택합니다.이벤트 리스너에는 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()})

또한 메시지를 브로드캐스트하는 현재 탭은 메시지를 실제로 수신하지 않고 동일한 도메인의 다른 탭 또는 창만 수신합니다.

사용자가 다른 웹 페이지를 로드하거나 setItem() 호출 직후에 탭을 닫으면 removeItem()이 발생할 수 있습니다. 제가 테스트한 , , 가, 제, 라, 라, 라, 라, 라, 라, well, well, well까지 언로딩을 보류하고 .message_broadcast()닫혔어요.매우 긴 for() 사이클을 넣으려고 테스트했는데도 사이클이 끝날 때까지 기다렸다가 닫힙니다.사용자가 중간에 탭을 닫으면 브라우저는 메시지를 디스크에 저장할 시간이 부족하기 때문에 이 방법은 트레이스 없이 메시지를 보내는 안전한 방법처럼 보입니다.

이를 위한 최신 API가 있습니다 - Broadcast Channel

다음과 같이 간단합니다.

var bc = new BroadcastChannel('test_channel');

bc.postMessage('This is a test message.'); /* send */

bc.onmessage = function (ev) { console.log(ev); } /* receive */

메시지가 단순히 DOMString일 필요는 없습니다.어떤 종류의 오브젝트라도 송신할 수 있습니다.

아마도 API의 청결성과는 별개로 오브젝트 문자열화가 없는 것이 이 API의 주요 장점일 것입니다.

현재는 Chrome 및 Firefox에서만 지원되지만 localStorage를 사용하는 polyfill을 찾을 수 있습니다.

jQuery를 기반으로 하지 않은 솔루션을 찾는 사용자는 Thomas M이 제공하는 솔루션의 일반 JavaScript 버전을 참조하십시오.

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);
    }
}

체크아웃 Across Tabs - 크로스 오리진 브라우저 탭 간에 쉽게 통신할 수 있습니다.postMessage API와 sessionStorage API를 조합하여 통신을 훨씬 쉽고 안정적으로 만듭니다.


다양한 접근법이 있으며 각각 장단점이 있습니다.각각에 대해 설명하겠습니다.

  1. 로컬 스토리지

    장점:

    1. 웹 스토리지는 단순히 쿠키의 향상으로 볼 수 있으며, 훨씬 더 큰 스토리지 용량을 제공합니다.Mozilla 소스 코드를 보면 5120KB(5MB, Chrome에서는 250만 문자와 동일)가 도메인 전체의 기본 스토리지 크기임을 알 수 있습니다.따라서 일반적인 4KB 쿠키보다 훨씬 더 많은 공간을 사용할 수 있습니다.
    2. 데이터는 모든 HTTP 요청(HTML, 이미지, JavaScript, CSS 등)에 대해 서버로 전송되지 않으므로 클라이언트와 서버 간의 트래픽 양이 줄어듭니다.
    3. localStorage에 저장된 데이터는 명시적으로 삭제될 때까지 유지됩니다.변경 내용은 저장되며 현재 및 향후 모든 사이트 방문에 사용할 수 있습니다.

    단점:

    1. 그것은 동일 원산지 정책에 따라 기능한다.따라서 저장된 데이터는 동일한 원본에서만 사용할 수 있습니다.
  2. 쿠키

    장점:

    1. 다른 거에 비해 AFAIK가 없어요.

    단점:

    1. 이름, 값, 유효기간 등을 포함한 쿠키 전체의 상한은 4KB입니다.대부분의 브라우저를 지원하려면 이름을 4000바이트 미만으로 유지하고 전체 쿠키 크기를 4093바이트 미만으로 유지하십시오.
    2. 데이터는 모든 HTTP 요청(HTML, 이미지, JavaScript, CSS 등)에 대해 서버로 반환되므로 클라이언트와 서버 간의 트래픽 양이 증가합니다.

    일반적으로 다음 사항이 허용됩니다.

    • 300개의 쿠키
    • 쿠키당 4096바이트
    • 도메인당 20개의 쿠키
    • 도메인당 81920바이트(최대 크기 4096=81920바이트의 쿠키 20개 지정)
  3. 세션 스토리지

    장점:

    1. 와와다 it it it to .localStorage.
    2. 변경은 창(또는 Chrome 및 Firefox와 같은 브라우저의 탭)별로만 사용할 수 있습니다.변경 내용이 저장되고 현재 페이지와 같은 창에서 사이트에 대한 향후 방문에 사용할 수 있습니다.창을 닫으면 저장소가 삭제됩니다.

    단점:

    1. 데이터는 설정된 창/탭 내에서만 사용할 수 있습니다.
    2. 데이터는 영구적이지 않습니다. 즉, 창/탭을 닫으면 데이터가 손실됩니다.
    3. 맘에 들다localStorage, tt 는 같은 패킷정책으로 동작합니다.따라서 저장된 데이터는 동일한 원본에서만 사용할 수 있습니다.
  4. Post Message(Post Message)

    장점:

    1. 발신기지간 통신을 안전하게 유효하게 합니다.
    2. 데이터 포인트로서 WebKit 실장(Safari 및 Chrome에서 사용)은 현재 (메모리 부족으로 인한) 제한을 적용하지 않습니다.

    단점:

    1. 현재 창에서 창을 열고 창을 열어 두어야 합니다.
    2. 보안상의 문제 - postMessage를 통해 문자열을 전송하면 다른 JavaScript 플러그인에 의해 퍼블리시된 다른 postMessage 이벤트를 픽업할 수 있으므로 반드시 구현해야 합니다.targetOrigin메시지 리스너에게 전달되는 데이터의 건전성 체크.
  5. Post Message + Session Storage 조합

    postMessage를 사용하여 여러 탭 간에 통신하고 동시에 새로 열린 모든 탭/창에서 sessionStorage를 사용하여 전달되는 데이터를 유지합니다.탭/창이 열려 있는 한 데이터는 유지됩니다.따라서 오프너 탭/창이 닫히더라도 열려 있는 탭/창은 새로고침 후에도 전체 데이터를 보유하게 됩니다.

이를 위해 CrossTabs라는 이름의 JavaScript 라이브러리를 작성했습니다.이 라이브러리는 postMessage API를 사용하여 크로스 오리진 탭/윈도우와 sessionStorage 간에 통신하여 열려 있는 탭/윈도우 ID를 존속하는 데 사용됩니다.

브라우저 탭과 창 사이에 메시지를 보내기 위한 라이브러리 sysend.js를 만들었습니다.라이브러리에 외부 종속성이 없습니다.

동일한 브라우저와 도메인에 있는 탭/윈도우 간의 통신에 사용할 수 있습니다.라이브러리는 Broadcast Channel(지원되는 경우) 또는 localStorage의 스토리지 이벤트를 사용합니다.

API는 매우 간단합니다.

sysend.on('foo', function(data) {
    console.log(data);
});
sysend.broadcast('foo', {message: 'Hello'});
sysend.broadcast('foo', "hello");
sysend.broadcast('foo', ["hello", "world"]);
sysend.broadcast('foo'); // empty notification

브라우저가 Broadcast Channel을 지원하면 리터럴오브젝트가 전송됩니다(그러나 실제로는 브라우저에 의해 자동시리얼라이즈 됩니다).지원되지 않을 경우 먼저 JSON으로 시리얼화되고 다른 쪽 끝에서 시리얼화 해제됩니다.

최신 버전에는 도메인 간 통신용 프록시를 만들기 위한 도우미 API도 있습니다(대상 도메인에 단일 HTML 파일이 필요합니다).

여기 데모가 있습니다.

또한 새로운 버전은 도메인 간 통신도 지원합니다.proxy.html 상의 및 콜 " " " " "proxy「 」의 「 」의 「 」

sysend.proxy('https://target.com');

(proxy.html은 라이브러리에서 스크립트태그가 1개밖에 없는 매우 단순한 HTML 파일입니다).

양방향 통신을 원할 경우 다른 도메인에서도 동일한 작업을 수행해야 합니다.

메모: local Storage를 사용하여 동일한 기능을 구현하는 경우 Internet Explorer에 문제가 있습니다.스토리지 이벤트는 동일한 창으로 전송되며, 이로 인해 이벤트가 트리거되며, 다른 브라우저의 경우 다른 탭/창에서만 호출됩니다.

사람들이 고려해야 할 또 다른 방법은 공유 근로자들이다.최첨단 개념인 것은 알지만 로컬 스토리지보다 훨씬 빠르고 부모/자녀 창 간의 관계가 필요 없는 릴레이를 공유 작업자에 생성할 수 있습니다.

이에 대한 자세한 내용은 여기를 참조하십시오.

같은 기원의 탭/윈도우 간에 동기화하고 통신하기 위한 작은 오픈 소스 컴포넌트가 있습니다(해임자 - 저는 기여자 중 한 명입니다!).localStorage.

TabUtils.BroadcastMessageToAllTabs("eventName", eventDataString);

TabUtils.OnBroadcastMessage("eventName", function (eventDataString) {
    DoSomething();
});

TabUtils.CallOnce("lockname", function () {
    alert("I run only once across multiple tabs");
});

추신: 이벤트가 거의 동시에 발생할 때 웹 소켓 연결에서 "Lock/mutex/sync" 컴포넌트의 대부분이 실패하기 때문에 여기서 실례를 무릅쓰고 추천했습니다.

공식 Broadcastchannel과 동일한 기능을 하는 모듈을 만들었지만 로컬 스토리지, 인덱스 데이터베이스 및 unix-sockets에 기반한 폴백을 가지고 있습니다.이를 통해 웹워커 또는 Node.js에서도 항상 작동합니다.pubkey 참조:브로드캐스트채널

제 블로그에 이런 기사를 썼어요.세션 공유브라우저 탭에 데이터를 저장합니다.

라이브러리를 사용하여storageManager다음과 같이 할 수 있습니다.

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

다른 시나리오에도 대응할 수 있는 편리한 방법이 있습니다.

이것은 개발입니다.storageTomas M이 Chrome에 대해 한 답변의 일부입니다.청취자를 추가해야 합니다.

window.addEventListener("storage", (e)=> { console.log(e) } );

저장소의 아이템을 로드/저장해도 이 이벤트는 실행되지 않습니다.다음 방법으로 수동으로 트리거해야 합니다.

window.dispatchEvent( new Event('storage') ); // THIS IS IMPORTANT ON CHROME

이제 열려 있는 모든 탭이 이벤트를 수신합니다.

언급URL : https://stackoverflow.com/questions/28230845/communication-between-tabs-or-windows