Заранее прошу прощения за странный вопрос
Есть сайт, который во фрейме отрывает другие (специфические) сайты.
Сайт, открывающийся во фрейме подлючает библиотеку api, который предстовляет собой оболочку для parent.postMessage().
И вот проблема. Как реализовать callback через postMessage()
Смысл в том, чтобы, через api можно было отправить назад во фрейм результат запроса, Сейчас реализовано так:
eos.api.set_data('data', (result)=>{
});
Сейчас api реализова так
let eos = {
api: {
set_data : (res, fun) => {
//Что делать с fun(), что бы его можно было визвать из `patern`
parent.postMessage(res,'***')
}
}
}
Т.е в родителе выполнятся фукция из api (set_data) и ее результат нужно обратно отправить в фрейм, и именно в callback функцию, переданою вторим парамертом api.
Еще раз прошу прощение за, возможно непонятный вопрос.
Все в коменрарии. Спасибо....
Нет, мы не можем передавать коллбэк через сообщения между окнами, так как данные обязательно должны быть либо простыми, либо наследовать от интерфейса Transferable. Подразумевается, что новая вкладка работает в обособленном потоке и передаваемые данные обязательно должны быть статичными (неизменяемыми) - вы получаете их копию, а не оригинал.
This is an abstract interface and there is no object of this type. The ArrayBuffer, MessagePort, ImageBitmap and OffscreenCanvas types implement this interface.
Вы можете применить The State Reducer Pattern, передавая между окнами объект с данными (Action), который вызовет изменение состояния через специальную функцию с ветвлением (Reducer).
<!DOCTYPE html>
<html>
<head>
<title>Frame</title>
</head>
<body>
<button>Send message</button>
<script>
(function() {
const ACTION = {
SHOW_ALL: 'SHOW_ALL',
SHOW_COMPLETED: 'SHOW_COMPLETED',
SHOW_ACTIVE: 'SHOW_ACTIVE'
}
const handler = ({origin, data}) => {
if (origin !== url) {
return;
}
switch (data) {
case ACTION.SHOW_ALL:
alert('Show all');
break;
case ACTION.SHOW_COMPLETED:
alert('Completed');
break;
case ACTION.SHOW_ACTIVE:
alert('Show active');
break;
default:
throw new Error(`Invalid action ${JSON.stringify(data)}`);
}
}
const { protocol, host, hash, href } = location;
const url = `${protocol}//${host}`;
const target = hash === "#child" ? opener : open(location.href + "#child");
window.addEventListener('message', (e) => handler(e));
document.querySelector('button').addEventListener('click', () =>
target.postMessage(ACTION.SHOW_ALL)
);
})();
</script>
</body>
</html>
Для запуска используйте какой-нибудь веб сервер, например, встроенный поумолчанию в третий python:
python3 -m http.server
Сборка персонального компьютера от Artline: умный выбор для современных пользователей