Ответ 1
Существует несколько способов передать многочастное сообщение обработчику postMessage
. Первый (и менее "чистый" способ) заключается в использовании символа разделителя, а затем передачи данных через строку.
Скажем, мы хотели передать идентификатор пользователя, действие и имя пользователя. Строка будет выглядеть так:
54|do_logout|chris
В обработчике postMessage
переданные данные могут быть split
(docs) на символе |
, тогда каждый сегмент сообщения может быть используется по мере необходимости.
Другой способ вместо ручного создания/разделения строки - использовать JSON (docs) для преобразования объекта в строку с одной стороны и использовать JSON для преобразования обратно в объект в обработчике.
var pass_data = {
'name':'Chris',
'id':54,
'action':'do_logout'
};
target_window.postMessage(JSON.stringify(pass_data), "http://www.example.net");
... затем в обработчике:
function (event) {
var pass_data = JSON.parse(event.data);
}
Обязательно проверьте, однако, что объект JSON
не предоставляется для всех агентов пользователя, особенно для старых. Существует множество (многих, многих) сторонних библиотек для поддержки поддержки JSON, поэтому не позволяйте отсутствию полного принятия напугать вас - JSON определенно является безопасным стандартом "продвижения вперед".
Не было бы лучше, если бы мы могли просто передать этот объект сразу? Ну, глядя в Firefox 6 (источник), данные, которые вы передаете обработчику postmessage, могут быть объектом. Объект будет сериализован, поэтому на этом фронте есть некоторые проблемы, но:
var pass_data = {
'name':'Chris',
'id':54,
'action':'do_logout'
};
target_window.postMessage(pass_data, "http://www.example.net");
Немного лучше, а? К сожалению, текущие версии IE будут иметь дело только со строками. Мне не удалось найти обсуждение будущих планов относительно postMessage
для IE 10. Кроме того, в IE 8/9 есть известная ошибка, которая разбивает postMessage
на что-либо иное, кроме фреймов. (источник).
Переход к конкретному аспекту вашего вопроса - обратные вызовы. Если вы не можете передать обратный вызов по имени функции, нет способа передать функцию; никаких анонимных функций для вас. Это связано с тем, как данные фактически передаются обработчику. На практике "нет" поддержки объектов как данных, за кулисами браузер превращает ваш прошедший объект в строку (сериализация).
Итак, вы должны понимать, что передача объекта точно такая же, как использование JSON для stringify
объекта перед передачей, только в первом случае браузер выполняет свою собственную сериализацию (и последующую нессеризацию) тогда как с последним маршрутом вам придется сериализовать /unserialize.
Точки вылета здесь:
- postMessage все еще имеет ограниченную поддержку кросс-браузера.
- Тенденция для более новых версий совместимых со стандартами браузеров заключается в том, чтобы разрешить прохождение объектов в дополнение к строкам
- Прошедший объект будет сериализован, поэтому ссылки на функции не будут разрешены
- Самая широкая поддержка "в дикой природе" предназначена для данных только для строк, что означает, что вам придется придерживаться строк и "упаковывать" ваши данные, как показано выше, если вы хотите поддерживать самые разные пользовательские агенты
- Internet Explorer погубит все ваши планы (в том числе семейные праздники).
Документация и ссылки
-
window.postMessage
: https://developer.mozilla.org/en/DOM/window.postMessage -
String.split
: https://developer.mozilla.org/en/JavaScript/Reference/Global_Objects/String/split - IE 8/9 Примечания к поддержке HTML5: http://blogs.msdn.com/b/ieinternals/archive/2009/09/16/bugs-in-ie8-support-for-html5-postmessage-sessionstorage-and-localstorage.aspx
-
JSON.stringify
: https://developer.mozilla.org/en/JavaScript/Reference/Global_Objects/JSON/stringify -
JSON.parse
: https://developer.mozilla.org/en/JavaScript/Reference/Global_Objects/JSON/parse