Одна проблема с кодом в вопросе заключается в том, что .postMessage()
вызывается сразу после установки нового .location.href
в popup
без ожидания события load
window
в
popup.location.href="http://domain_two.com"
popup.postMessage(JSON.stringify(formData),
"http://domain_two.com");
Для достижения ожидаемого результата вы можете контролировать процесс с оригинального window
('index.html').Каждый window.name
имеет уникальное значение.Когда <form>
передается в "http://domain_one.com"
, результирующий FormData
может быть преобразован в ArrayBuffer
и переведен в index.html
, тогда popup
(a.html
) location.href
устанавливается в "http://domain_two.com"
.При load
событии b.html
.postMessage()
name
от window
до index.html
.Затем FormData
передается в .postMessage()
, где b.html
получает FormData
, который был первоначально отправлен в b.html
.
(проверки origin
, возможно, должны быть скорректированы по приведенному ниже коду. Код был протестирован в plnkr, где имитация междоменного обмена сообщениями не 1: 1, хотя и должна обеспечивать образец для выполнения требования).
index.html (opener
)
<!DOCTYPE html>
<html>
<head>
</head>
<body>
<script>
// open `popup`
const popup = window.open('a.html');
// create random values to assign to `name` at `a.html` and `b.html`
const [firstName, lastName] = [...Array(2)].map(_ => new Uint32Array(16));
[firstName, lastName].forEach(buffer => window.crypto.getRandomValues(buffer));
const [decoder, encoder] = [new TextDecoder(), new TextEncoder()];
const [first, last] = [firstName, lastName].map(buffer => decoder.decode(buffer));
// set `name` of `popup` (`a.html`) to `first`
popup.name = first;
let data;
window.addEventListener("message", e => {
// check `name` of `source`
if (e.source.name === first) {
console.log(e.source.name);
// store `formData`
data = decoder.decode(e.data);
console.log(e, JSON.parse(decoder.decode(e.data)));
// set `name` of `popup` to `last`
popup.name = last;
// redirect `popup` to `b.html`
popup.location.href = "b.html";
}
// check if `name` of `source` (`b.html`) is `last`
if (e.source.name === last) {
// encode the stored `formData`
let curr = encoder.encode(data);
console.log(e.source.name, e.data);
// transfer `formData` to `b.html`
e.source.postMessage(curr.buffer, e.source.location.href, [curr.buffer]);
// data = void 0;
}
})
</script>
</body>
</html>
a.html (popup
, "http://domain_one.com"
)
<!DOCTYPE html>
<html>
<head>
</head>
<body>
a
<form>
<input name="input">
<input type="submit">
</form>
<script>
document.forms[0].onsubmit = e => {
// prevent default `form` submission
e.preventDefault();
// pass `form` to `FormData`
const formData = new FormData(e.target);
// encode `formData` as a `Uint8Array`
const encoded = new TextEncoder().encode(JSON.stringify([...formData.entries()]));
console.log(encoded);
// transfer `encoded` to `opener` (`index.html`)
opener.postMessage(encoded.buffer, opener.location.href, [encoded.buffer]);
}
</script>
</body>
</html>
b.html (popup
, "http://domain_two.com"
)
<code><!DOCTYPE html>
<html>
<head>
</head>
<body>
b
<script>
const decoder = new TextDecoder();
let data;
window.addEventListener("message", receiveMessage, false);
function receiveMessage(event) {
// check `origin` of `event`
if (event.origin !== opener.location.origin)
return;
console.log(event);
// process `formData` from `popup`
data = JSON.parse(decoder.decode(event.data));
// do stuff with `formData`
p.textContent = JSON.stringify(data, null, 2);
}
// wait for `load` event to be dispatched before posting message to `opener`
onload = () => {
opener.postMessage("ok", opener.location.href);
}
</script>
<pre id="p">
plnkr