Как стать автором
Обновить

Комментарии 21

Добавьте в пример <meta charset=utf-8>
А почему не что-то готовое, например github.com/tejacques/crosstab? реакцию на зависшую вкладку делали, как в этом случае будет реализованы выборы?
Я в принципе понимаю почему не shared workers, но почему comet, а не websockets?
Добавил тег.
Вешать вкладку не пробовал ещё, но полагаю поведение будет почти аналогично если вкладку закрыть, то есть просто js перестанет работать на одной из вкладок. Соответственно если это была мастер вкладка то остальные вкладки перестав получать уведомления от мастер вкладки просто выберут другого мастера себе и всё.
Если вкладка потом отвиснет и продолжит работу то может оказаться что у нас 2 мастера что конечно не хорошо. но пока этот случай я не обрабатываю.

Первый коммит в тот репозиторий который вы дали произведён позже того как я написал своё решение. Просто я с опубликацией своего решения сильно затянул время. Хотя не исключаю что и в начале 2013 года были аналогичные скрипты.
caniuse.com говорит нам
In private browsing mode, Safari, iOS Safari and the Android browsers do not support setting sessionStorage or localStorage

Ваша решение работает в этих условиях?
А вы как думаете?
var curent_custom_id = Math.random()+"_"+Math.random()+"_"+Math.random()+"_"+Math.random()+"_"+Math.random()

омг…

+ В глобальной области нехорошо так лихо функции писать. AMD/requireJS в помощь.
+ куски копипасты в коде.

Лучше бы вы взяли готовый модуль.
Переменная curent_custom_id объявлена с использованием слова var внутри функции, а значит она локальна. Для проверки можно попробовать получить значение переменной из консоли.
Вместо Math.random() красивее использовать new Date().getTime().toString().
Ради всего святого, выберите один стиль для кода, и пройдитесь по нему jshint-ом, мне было больно читать.
НЛО прилетело и опубликовало эту надпись здесь
Ну и по модульности, я вот не понял, по какому принципу код разделен на две части, одна внутри страницы, а другая в файле. Между этими двумя частями высокая логическая связанность (обе знают друг о друге и по отдельности не работают), лучше объединить все в один модуль.
Когда-то давно публиковал статейку, достаточно justforfun'овый и хардкорный способ: habrahabr.ru/post/167265/
В приведенном примере возможно баг.
Открыл поочередно три вкладки, первая мастер, прочие две слейв. Закрываю мастер и все слейвы становятся мастерами.
100%, я когда-то реализовывал подобное, столкнулся с той же проблемой, в результате нужно делать выборы нового главное, проще всего это сделать через приоритеты, например, при старте каждой вкладки писать в localstorage время ее создания, а при выборах, например, самая последняя вкладка будет иметь приоритет, если она не взяла на себя роль нового главного за N миллисекунд, то берет более старая и т.д.
Для этого мастер вкладка отправляет сообщение всем вкладкам каждые 150 миллисекунд о том, что она вообще есть.

Попробуйте менять мастера на onbeforeunload.
Вниманию Levhav, как Вы сами знаете, если зависшая вкладка отвисает, то становится 2 мастера, и как обнаружил beliyadm, больше одного мастреа становится не только в этом случае. В общем, механизм выбора нового мастреа работает через раз. Попробуйте сами, создайте 30 вкладок, выводить master/slave в заголовок, чтобы проще ориентироваться прямо по вкладкам, и закрывайте их по одной или пачками по 2-3, там еще один эффект. В общем, я когда-то сталкивался с этой проблемой и уже решал ее, сейчас нашел старое решение в коде приложения и перенес его в пример клиентского приложения в своем сервере приложений Impress для node.js. Код открыт, можете взять идею тут, я выделил 150 строк.
Да так и сделаю. Воспользуюсь вашим советом про реализацию через приоритеты. Через пару тройку дней опубликую правки.
О, еще такая штука, я написал, что за приоритет лучше брать время создания вкладки, но теоретически, оно может и совпасть у нескольких вкладок. В своем примере я сначала использовал время последнего хартбита (сигнала об активности) от этой вкладки, записанного в localStorage — тут я ошибся, оно совпадало уже чаще и я перешел на приоритеты по id вкладки, чем больше id, при условии, что время не просрочено, тем выше приоритет. Есть, конечно, слабая вероятность, что вкладки неправильно выберут мастера из-за того, что localStorage не имеет локинга, т.е. мы теряем преимущества однопоточности JavaScript при доступе к разделяемым данным, и пока одна вкладка читала последовательно несколько ключей в localStorage, то другая могла изменить один из них. Мы не можем сделать локинг или транзакцию тут. Но в реальности мне не удалось запутать эту реализацию. Приведу скриншот того, как выглядит localStorage при работе программы: image
Тут видно, что я пишу хартбит для каждой вкладки, старые хартбиты удаляются мастером, как только время хартбита устаревает, вкладка или закрыта или зависла. Новые вкладки занимают место (слоты) старых. Работает это по принципу «один за всех, и все за одного», т.е. мастер следит за каждым, а за мастером следят все. Отдельно пишется impress.rpc.master — id текущего мастера и impress.rpc.newtab — id последней созданной вкладки. Писать impress.rpc.master нужно потому, что это создает событие изменения localStorage и все клиенты быстрее понимают, что новый мастер уже выбран, а impress.rpc.newtab так же создает событие изменения localStorage для того, чтобы мастер быстрее отправил свой хартбит, это ускоряет подключение новой вкладки при старте. В общем, вышло нетривиальное решение. Надеюсь, это поможет при реализации кода.
Классический вопрос в хабе «Клиентская оптимизация»: что делает здесь этот топик?
Ну «Клиентская оптимизация» потому, что позволяет сократить кол-во операций, соединений и других ресурсов в браузере. То, что дублировалось в 10 вкладках, может делаться в одной и использоваться в остальных через механизм межвкладочного взаимодействия, например, автор использует это для снижения кол-ва comet соединений, но дать ясные пояснения по этому поводу не мешало бы. Вот использование Comet в то время, как можно было бы применить более современные Server-Sent Events или WebSocket — это для меня загадка. И хаб «ajax» тоже непонятно к чему тут.
За пол года на тостере и не только было несколько вопросов подобных этим
Long Polling тормозит браузер — как это исправить?
При запросе ajax и попытке перейти по ссылке браузер виснет

Люди используя Ajax или WebSocket удивлялись что у них не работает это на множестве вкладок, по этому я это и добавил хаб ajax.
Для WebSocket описанное решение на мой взгляд тоже актуально.
Зарегистрируйтесь на Хабре, чтобы оставить комментарий