与iframe进行跨域通信时,异步/等待应答onMessage事件

尼克森85

我有一个iframe,它正在与其父窗口进行通信,以通过postMessage方法设置和获取一些必要的cookie

首先,iframe应用程序中的一个函数从父窗口请求CookieA。

    function requestCommunication(topic, customerId) {

            function cookieAvailable() {
                return new Promise((resolve) => resolve(getCookieData('cookieName'));
                });
            }

            console.log(cookieAvailable());

            if(!!cookieAvailable()) {
                //doStuff        
            }
     }

cookieAvailable()触发从iframe发送到parent.window的消息。反过来,窗口返回cookie及其数据作为字符串。通过使用以下操作完成此操作:

 async function getCookieData(cookieName) {

        const {data} = await new Promise(resolve => {

            window.onmessage = (event) => {
                resolve(event);
            }
        });

        var cookieContent = JSON.parse(data);
        var cookieContentData = JSON.parse(cookieContent.data);

        return cookieContentData; //this returns the cookie data (in almost all cases)
    }    

我没有如何正确使用诺言将其移交给我的初始触发功能。我将不胜感激。

海道

您的代码中存在明显的问题和反模式。cookieAvailable将返回一个Promise,因此您的支票if(!!cookieAvailable()) {永远是真实的。您将要等待该Promise解决,然后再检查是否确实存在cookie。

但是实际上,您的cookieAvailable函数将thisChatClient.cookie.getCookieData不返回任何内容的Promise包装器:如果确实返回了Promise,则直接将其返回,无需将其包装在Promise中。
而且,如果返回同步结果,则只能通过将其包装在Promise中来放松

async function requestCommunication(topic, customerId) {

  function cookieAvailable() {
    // this is already a Promise
    return thisChatClient.cookie.getCookieData('sess_au');
  }

  const isCookieAvailable = await cookieAvailable();

  if (!!isCookieAvailable) {

  }
}
requestCommunication().catch(console.error);

现在,所有这些都无助于正确回答您的问题:两个代码块之间的链接根本不清楚。

没有什么叫任何功能。

getCookieData将等待一个MessageEvent,而不会让任何人知道它正在等待它。

我不确定您是如何计划让iframe知道应该将包含此信息的消息发送到窗口的,但是您必须考虑这一点。

但是在去那之前,我应该注意:尽管很诱人,但是将事件包装在Promises中通常不是一个好主意。

事件和承诺是不同的事物,后者应仅解决一次,而前者可能会多次触发,并且来自不同的来源。

IMM,只有在您确定事件只会触发一次时才这样做。使用MessageEvent,您远不了解它。
您的用户很可能在其浏览器上具有一个扩展名,该扩展名将使用postMessage作为通信方式。如果将此扩展名添加到所有iframe上,则您的代码已损坏。

相反,您应该检查MessageChannel API,它将为您提供通信方式,可以确保您将是唯一使用的通信方式。
我认为此答案不是解释此API如何工作的正确位置,但请看一下概述了基本知识的概述

由于您将确保控制两端,因此您可以从那里建立一个基于Promise的系统。

在您的主页上,您将准备MessageChannel对象,并在侦听响应时将其发送到iframe。收到答复后,您就可以解决您的Promise。

在iframe中,您将在窗口上添加一个侦听器以捕获MessageChannelPort。发生这种情况时,您将向您的服务询问cookie,然后通过MessageChannel的端口将其发送回去。

即使在交换过程中在主窗口上出现一条消息,您也可以确保它不会成为您正在等待的消息。

// Sets up a new MessageChannel
// so we can return a Promise
function getCookieData() {
  return new Promise((resolve) => {
    const channel = new MessageChannel();
    // this will fire when iframe will answer
    channel.port1.onmessage = e => resolve(e.data);
    // let iframe know we're expecting an answer
    // send it its own port
    frame.contentWindow.postMessage('getCookie', '*', [channel.port2]);  
  });
}

frame.onload = async e => {
  const frameHasCookie = await getCookieData();
  console.log(frameHasCookie);
};

frame.src = generateFrameSRC();

function generateFrameSRC() {
  // The content of your iframe
  const cont = `
<html>
  <head>
    <script>
      const originClean = "null";
      onmessage = async e => {
        // only if it's the origin we expected 
        // and if it does send a  MessagePort 
        // and the message is "getCookie"
        if(e.origin === originClean && e.ports && e.data === "getCookie") {
          const data = await asyncData();
          // respond to main window
          e.ports[0].postMessage(data);
        }
      };
      function asyncData() {
        return new Promise(resolve => 
          setTimeout(() => resolve("the data"), 1000)
        );
      }
    <\/script>
  </head>
  <body>
    hello
  </body>
</html>`;
  return 'data:text/html,' + encodeURIComponent(cont)
}
<iframe id="frame"></iframe>

本文收集自互联网,转载请注明来源。

如有侵权,请联系[email protected] 删除。

编辑于
0

我来说两句

0条评论
登录后参与评论

相关文章

来自分类Dev

从父级到子级iframe进行跨域通信

来自分类Dev

iframe跨域通信-调整大小事件-跨浏览器?

来自分类Dev

使用事件发射器和服务进行跨组件通信的角度异步调用

来自分类Dev

如何从iframe(跨域)访问onfocus事件?

来自分类Dev

调用方法异步而不等待应答

来自分类Dev

调用方法异步而不等待应答

来自分类Dev

在跨网域的iframe中监听按键事件

来自分类Dev

如何跨多个iframe(同一域)创建点击事件?

来自分类Dev

通过事件网关异步应答Alexa智能家居技能时,如何回答AWS Lambda?

来自分类Dev

通过独立作用域进行基于AngularJS事件的通信

来自分类Dev

通过独立作用域进行基于AngularJS事件的通信

来自分类Dev

异步/等待事件

来自分类Dev

当我需要等待事件时如何使方法异步

来自分类Dev

跨域postMessage,标识iFrame

来自分类Dev

从跨域iframe接收数据

来自分类Dev

如何使用asyncio.Future将基于事件的通信转换为异步/等待

来自分类Dev

等待目标应答时 tcp/udp 源端口的状态

来自分类Dev

通过异步/等待服务器通信?

来自分类Dev

通过iframe打印pdf(跨域)

来自分类Dev

iFrame中的页面顶部-跨域

来自分类Dev

JavaScript跨网域iframe调整大小

来自分类Dev

跨域访问iframe内容的高度

来自分类Dev

jQuery跨域iframe高度问题

来自分类Dev

iFrame中的页面顶部-跨域

来自分类Dev

跨域访问iframe内容的高度

来自分类Dev

选择对象和跨域iframe?

来自分类Dev

js跨网域到iframe

来自分类Dev

通过iframe打印pdf(跨域)

来自分类Dev

需要进行异步澄清并等待