Szukałem sposobu, jak komunikować się między wieloma kartami lub oknami w przeglądarce (w tej samej domenie, a nie CORS) bez pozostawiania śladów. Rozwiązań było kilka:
Pierwsze jest prawdopodobnie najgorszym rozwiązaniem - musisz otworzyć okno z bieżącego okna, a wtedy możesz komunikować się tylko wtedy, gdy masz otwarte okna. Jeśli ponownie załadujesz stronę w którymkolwiek z okien, najprawdopodobniej stracisz komunikację.
Drugie podejście, wykorzystujące postMessage, prawdopodobnie umożliwia komunikację między źródłami, ale występuje ten sam problem, co pierwsze podejście. Musisz zachować obiekt okna.
Trzeci sposób, korzystając z plików cookie, przechowują w przeglądarce pewne dane, które w efekcie mogą wyglądać jak wysyłanie wiadomości do wszystkich okien w tej samej domenie, ale problem polega na tym, że nigdy nie wiadomo, czy wszystkie zakładki przeczytały już „wiadomość”, czy nie wcześniej sprzątanie. Musisz wprowadzić jakiś limit czasu, aby okresowo odczytywać plik cookie. Ponadto jesteś ograniczony maksymalną długością pliku cookie, która wynosi 4KB.
Czwarte rozwiązanie, wykorzystujące localStorage, wydawało się przezwyciężać ograniczenia plików cookie, a nawet można słuchać za pomocą zdarzeń. Sposób korzystania z niego opisano w zaakceptowanej odpowiedzi.
Edytuj 2018: zaakceptowana odpowiedź nadal działa, ale jest nowsze rozwiązanie dla nowoczesnych przeglądarek, aby używać BroadcastChannel. Zobacz drugą odpowiedź, aby zapoznać się z prostym przykładem opisującym, jak łatwo przesyłać wiadomości między kartami przy użyciu BroadcastChannel.
źródło
Odpowiedzi:
Edycja 2018: W tym celu możesz lepiej użyć BroadcastChannel, zobacz inne odpowiedzi poniżej. Jeśli jednak nadal wolisz używać magazynu lokalnego do komunikacji między kartami, zrób to w ten sposób:
Aby otrzymać powiadomienie, gdy karta wysyła wiadomość do innych zakładek, wystarczy powiązać zdarzenie „przechowywanie”. Na wszystkich kartach zrób to:
Funkcja
message_receive
będzie wywoływana za każdym razem, gdy ustawisz jakąkolwiek wartość localStorage na dowolnej innej karcie. Detektor zdarzeń zawiera również dane nowo ustawione na localStorage, więc nie musisz nawet analizować samego obiektu localStorage. Jest to bardzo przydatne, ponieważ można zresetować wartość zaraz po jej ustawieniu, aby skutecznie usunąć wszelkie ślady. Oto funkcje przesyłania wiadomości:Więc teraz, gdy twoje karty połączą się ze zdarzeniem onstorage i masz zaimplementowane te dwie funkcje, możesz po prostu rozesłać wiadomość do innych kart, wywołując na przykład:
Pamiętaj, że dwukrotne wysłanie dokładnie tej samej wiadomości zostanie propagowane tylko raz, więc jeśli chcesz powtarzać wiadomości, dodaj do nich unikalny identyfikator, np.
Pamiętaj też, że bieżąca karta, która emituje wiadomość, w rzeczywistości jej nie odbiera, tylko inne karty lub okna w tej samej domenie.
Możesz zapytać, co się stanie, jeśli użytkownik załaduje inną stronę internetową lub zamknie swoją kartę tuż po wywołaniu setItem () przed removeItem (). Cóż, z moich własnych testów przeglądarka wstrzymuje wyładowywanie do czasu zakończenia całej funkcji
message_broadcast()
. Testowałem, aby umieścić tam bardzo długi cykl for () i nadal czekałem na zakończenie cyklu przed zamknięciem. Jeśli użytkownik zabije kartę w międzyczasie, przeglądarka nie będzie miała wystarczająco dużo czasu, aby zapisać wiadomość na dysku, dlatego takie podejście wydaje mi się bezpiecznym sposobem wysyłania wiadomości bez żadnych śladów. Komentarze mile widziane.źródło
Do tego celu służy nowoczesne API - Broadcast Channel
To jest tak proste, jak:
Prawdopodobnie poza czystością API jest to główna zaleta tego API - brak ciągnienia obiektów.
Obecnie obsługiwane tylko w Chrome i Firefox, ale możesz znaleźć polyfill, który używa localStorage.
źródło
Dla poszukujących rozwiązania nie opartego na jQuery, oto prosta wersja JavaScript rozwiązania dostarczonego przez Thomasa M.
źródło
Checkout AcrossTabs - Łatwa komunikacja między kartami przeglądarki z różnych źródeł. Używa połączenia API postMessage i sessionStorage, aby komunikacja była znacznie łatwiejsza i niezawodna.
Istnieją różne podejścia, a każde z nich ma swoje zalety i wady. Porozmawiajmy o każdym:
Lokalny magazyn
Plusy :
Wady :
Ciasteczka
Plusy:
Cons:
Dane są odsyłane do serwera przy każdym żądaniu HTTP (HTML, obrazy, JavaScript, CSS itp.) - zwiększając natężenie ruchu między klientem a serwerem.
Zwykle dozwolone są następujące czynności:
sessionStorage
Plusy:
localStorage
.Cons:
localStorage
tt działa na zasadzie tego samego pochodzenia . Zatem przechowywane dane będą dostępne tylko w tym samym miejscu pochodzenia.Wyślij wiadomość
Plusy:
Cons:
targetOrigin
i sprawdzeniu poprawności danych przekazywanych do nasłuchiwania wiadomości.Połączenie PostMessage + SessionStorage
Używanie postMessage do komunikacji między wieloma kartami i jednoczesne używanie sessionStorage we wszystkich nowo otwartych kartach / oknach w celu utrwalenia przekazywanych danych. Dane będą przechowywane tak długo, jak długo karty / okna pozostaną otwarte. Tak więc, nawet jeśli karta / okno otwieracza zostanie zamknięte, otwarte karty / okna będą miały wszystkie dane nawet po odświeżeniu.
Napisałem w tym celu bibliotekę JavaScript, nazwaną AcrossTabs, która używa API postMessage do komunikacji między kartami / oknami pochodzącymi z różnych źródeł i sessionStorage, aby zachować tożsamość otwartych kart / okien tak długo, jak długo żyją.
źródło
AcrossTabs
, czy można otworzyć inną witrynę w innej karcie i przenieść z niej dane do karty nadrzędnej? Będę mieć dane uwierzytelniające dla innej witryny.Inną metodą, którą ludzie powinni rozważyć, są Shared Workers. Wiem, że jest to nowatorska koncepcja, ale możesz utworzyć przekaźnik na współdzielonym pracowniku, który jest DUŻO szybszy niż lokalny magazyn i nie wymaga relacji między oknem nadrzędnym / podrzędnym, o ile jesteś na tym samym początku.
Zobacz moją odpowiedź tutaj, aby zapoznać się z dyskusją, którą przeprowadziłem na ten temat.
źródło
Jest mały komponent open source do synchronizacji / komunikacji między kartami / oknami tego samego pochodzenia (zastrzeżenie - jestem jednym z współautorów!)
localStorage
.https://github.com/jitbit/TabUtils
PS Pozwoliłem sobie polecić to tutaj, ponieważ większość komponentów "blokujących / mutex / synchronizujących" zawodzi na połączeniach websocket, gdy zdarzenia zachodzą prawie jednocześnie
źródło
Stworzyłem bibliotekę sysend.js , jest bardzo mała, możesz sprawdzić jej kod źródłowy. Biblioteka nie ma żadnych zewnętrznych zależności.
Możesz go używać do komunikacji między kartami / oknami w tej samej przeglądarce i domenie. Biblioteka używa BroadcastChannel, jeśli jest obsługiwana, lub zdarzenia magazynu z localStorage.
API jest bardzo proste:
gdy Twoja przeglądarka obsługuje BroadcastChannel, wysłała obiekt literału (ale w rzeczywistości jest on automatycznie serializowany przez przeglądarkę), a jeśli nie, jest najpierw serializowany do JSON i deserializowany na drugim końcu.
Najnowsza wersja ma również pomocniczy interfejs API do tworzenia proxy do komunikacji między domenami. (wymaga pojedynczego pliku html w domenie docelowej).
Oto demo .
EDYCJA :
Nowa wersja wspiera również Cross-Domain komunikację, jeśli zawierają specjalny
proxy.html
plik w domenie docelowej i wywołaniaproxy
funkcji z domeny źródłowej:(proxy.html to bardzo prosty plik html, który ma tylko jeden tag script z biblioteką).
Jeśli chcesz dwukierunkową komunikację, musisz zrobić to samo w
target.com
domenie.UWAGA : Jeśli zaimplementujesz tę samą funkcjonalność przy użyciu localStorage, w IE występuje problem. Zdarzenie magazynu jest wysyłane do tego samego okna, które wyzwoliło zdarzenie, a dla innych przeglądarek jest wywoływane tylko dla innych kart / okien.
źródło
Stworzyłem moduł, który działa na równi z oficjalnym Broadcastchannel, ale ma awaryjne rozwiązania oparte na localstorage, indexeddb i unix-sockets. Daje to pewność, że zawsze działa nawet z Webworkers lub NodeJS. Zobacz pubkey: BroadcastChannel
źródło
Napisałem artykuł na ten temat na swoim blogu: http://www.ebenmonney.com/blog/how-to-implement-remember-me-functionality-using-token-based-authentication-and-localstorage-in-a- Aplikacja internetowa .
Korzystając z utworzonej przeze mnie biblioteki,
storageManager
możesz to osiągnąć w następujący sposób:Istnieją również inne wygodne metody obsługi innych scenariuszy
źródło
To jest
storage
część rozwojowa odpowiedzi Tomasa M. na Chrome. Musimy dodać słuchaczaZaładuj / zapisz element w magazynie, a nie uruchom tego zdarzenia - MUSIMY wywołać go ręcznie przez
a teraz wszystkie otwarte karty otrzymają zdarzenie
źródło