CallBack с фрейма в родитель

109
12 февраля 2022, 08:40

Заранее прошу прощения за странный вопрос

Есть сайт, который во фрейме отрывает другие (специфические) сайты. Сайт, открывающийся во фрейме подлючает библиотеку 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.

Еще раз прошу прощение за, возможно непонятный вопрос.

Все в коменрарии. Спасибо....

Answer 1

Нет, мы не можем передавать коллбэк через сообщения между окнами, так как данные обязательно должны быть либо простыми, либо наследовать от интерфейса 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
READ ALSO
В vscode не работает intelligence

В vscode не работает intelligence

Переустановил виндуОткрываю проект на vscode 1

151
Как задать стили элементу дочерним элементам через класс?

Как задать стили элементу дочерним элементам через класс?

Однако в этом коде делается подсветка при наведении на каждое слово, а мне нужно так:

106
Убрать всё лишнее из строки

Убрать всё лишнее из строки

Надо убрать пробелы в начале и в конце строки, повторяющиеся пробелы в середине (оставить по одному) и всё кроме цифр, русских и английских...

101
Vuej.js; Крашится Chrome при дебаге

Vuej.js; Крашится Chrome при дебаге

У меня возникли проблемы с select в vue, даже в простейшем примереЯ создаю проект с помощью команды vue init webpack-simple

147