#javascript #google-chrome #web-worker #broadcast-channel #sharedarraybuffer
#javascript #google-chrome #веб-работник #Широковещательный канал #sharedarraybuffer
Вопрос:
Broadcast Channel API кажется альтернативой postMessage или Channel Messaging API (он же MessageChannel).) Я успешно использовал оба в последних версиях Google Chrome для отправки буферов общего массива; однако у меня возникли проблемы с отправкой буфера общего массива с использованием API широковещательного канала.
Документ Mozilla наhttps://developer.mozilla.org/en-US/docs/Web/API/BroadcastChannel ссылается на спецификацию в https://html.spec.whatwg.org/multipage/web-messaging.html#broadcastchannel , в котором говорится:
Для каждого назначения в destinations…
- Пусть данные будут структурированы как сериализованные (serialized, targetRealm). Если это вызывает исключение, перехватите его, запустите событие с именем messageerror в пункте назначения, используя MessageEvent, с атрибутом origin, инициализированным сериализацией sourceOrigin , а затем прервите эти шаги.
StructuredDeserialize определяется в https://html.spec.whatwg.org/multipage/structured-data.html#structureddeserialize и, похоже, предполагает, что он охватывает SharedArrayBuffers:
- В противном случае, если сериализовано.[[Тип]] — «SharedArrayBuffer», тогда: Если соответствующий кластер агентов targetRealm не сериализован.[[AgentCluster]], а затем вызвать DOMException «DataCloneError» DOMException. В противном случае задайте значение новому объекту SharedArrayBuffer в targetRealm, значение внутреннего слота которого [[ArrayBufferData]] сериализуется.[[ArrayBufferData]] и чье [[ArrayBufferByteLength]] значение внутреннего слота сериализуется.[[ArrayBufferByteLength]].
Читая это, мне кажется, что это должно сработать, но я получаю сообщение event, в котором данные просто null
. Если бы это было проблемой безопасности, я бы ожидал получить событие messageerror вместо события message.
Вот мой минимальный тестовый пример:
broadcast-test.html (должен обслуживаться с http-сервера — не будет работать через file://)
<!DOCTYPE html>
<html>
<head><title></title></head>
<body>
<script src="broadcast-test.js"></script>
</body>
</html>
broadcast-test.js
const isThisTheWorker = this.document === undefined
const broadcastChannel = new BroadcastChannel('foo')
if (!isThisTheWorker) {
broadcastChannel.addEventListener('message', (event) => {
console.log('main received', event.data)
const sab = new SharedArrayBuffer(100)
broadcastChannel.postMessage({ hello: 'from main', sab })
})
var myWorker = new Worker('broadcast-test.js')
}
else {
broadcastChannel.addEventListener('message', (event) => {
console.log('worker received', event.data)
})
broadcastChannel.postMessage({ hello: 'from worker' })
}
Наблюдаемый вывод на консоль: (Chrome 84.0.4147.135 в Windows 10)
main получено {привет: «от работника»}
рабочий получил null
Неправильная реализация Google Chrome или я неправильно понимаю спецификацию?
Комментарии:
1. что происходит, когда вы регистрируете событие в консоли? (не event.data)
2. должно работать и на самом деле работает — это две разные вещи — тот факт, что что-то есть «в стандарте» — не означает, что это было реализовано (пока) …. о, и, кстати, это не работает и в firefox
3.@altruios
main received MessageEvent {isTrusted: true, data: {…}, origin: "http://localhost:1234", lastEventId: "", source: null, …}
broadcast-test.js:50 worker received MessageEvent {isTrusted: true, data: null, origin: "http://localhost:1234", lastEventId: "", source: null, …}
Слишком много пропущенных свойств для публикации в этом пространстве.4. Очевидно, что ни один браузер не поддерживает это , а с грядущими ограничениями COOP / COEP заставить это работать будет еще сложнее…