postMessage 方法的小坑

作者: 文者字清 | 来源:发表于2019-05-22 11:45 被阅读0次
postMessage

知识点

MDN对postMessage方法的介绍

场景

在很多时候,我们会遇到编辑操作,点击编辑按钮打开一个新页面,在新页面操作完成之后,需要对父页面做操作,比如:列表刷新。这时需要两个窗口通信,通信方式有很多,比如:在父页面window上添加一些callbackId,然后子页面的window.opener[callbackId]调用对应函数。但是为了支持 electron(新的页面的window.opener是一个被electron重写的对象,只有window的少数方法和属性),所以选择 postMessage。想要把 postMessage 和 addEventListener 这种异步通信方式封装成 promise 形式,所以就踩了个坑。

方案&代码


// 方案一:trigger时返回一个promise,在注册的回调函数里resolve,子页面就可以拿到cb的返回值。

  class Talk{

    // 父页面调用的方法 
    register(cb){
      // 打开一个新页面
      window.open('xxx');
      // 监听
      window.addEventListener('message', e => {
        const cbResult = cb(e.data.data);
        // resolve
        e.data.resolve(cbResult);
      })
    }
    // 子页面调用的方法
    trigger = (...args) => {
      return new Promise((res, rej) => {
        // 将 res 传到父页面
        const data = {
          resolve:res,
          data: args
        }
        // 看文档我们知道,postMessage已经支持了复杂类型的数据,而不仅仅是字符串
        // 但是在promise里,还是只能为字符串,具体原因不清楚,这里会想到JSON.stringify
        // JSON.stringify 会过滤掉数据里的函数、Symbol、undefined
        // 所以,这种方式行不通了
        window.opener.postMessage(data);
      })
      
    }

  }

// 方案二:trigger时返回一个promise,子页面发消息 -> 父页面收到消息,再发送cb返回值 -> 子页面收到消息,执行resovle

  class Talk{

    // 父页面调用的方法
    register(cb){
      // 打开一个新页面
      const opener = window.open('xxx');
      // 监听
      window.addEventListener('message', e => {
        const cbResult = cb(e.data.data);
        // 发送消息, 需要调用子页面window的postMessage方法,第二个参数是targetOrigin,* 为不限制
        opener.postMessage(cbResult, '*');
      })
    }
    // 子页面调用的方法
    trigger = (...args) => {
      window.opener.postMessage(...args);
      return new Promise((res, rej) => {
        // 子页面监听事件
        window.addEventListener('message', e => {
          res(e.data)
        })
      })
    }
  }

总结

  • 在promise里,postMessage 传输的数据只能为字符串
  • JSON.stringify 会过滤掉数据里的函数、Symbol、undefined
  • window.addEventListener(type,cb, option ), option.once = true 时,只会调用一次listener,然后这个type的listener都会被 remove,参考MDN

相关文章

  • postMessage 方法的小坑

    知识点 MDN对postMessage方法的介绍 场景 在很多时候,我们会遇到编辑操作,点击编辑按钮打开一个新页面...

  • iframe

    一、iframe跨域的几种常用方法 1、postmessage window.postMessage方法可以安全地...

  • 使用 postMessage + iframe 实现跨域通信

    一、postMessage window.postMessage() 方法可以安全地实现跨源通信。通常,对于两个不...

  • postMessage

    postMessage是html5引入的API,postMessage()方法允许来自不同源的脚本采用异步方式进行...

  • 跨域问题2

    使用window.postmessage方法来跨域 Html5里有一个属性window.postmessage也可...

  • JS跨域

    JS跨域--H5 postMessage window.postMessage是html5中新增了一个新的跨域方法...

  • postMessage踩坑实践

    前言 在低代码编辑器中进行页面预览常常不得不用到iframe进行外链的url引入,这就涉及到了预览页面与编辑器页面...

  • vue中js与ios交互postMessage问题

    window.webkit.[ios注入的对象].[方法名].postMessage([js传递给ios的参数]) ;

  • 父子iframe通信问题

    主页面 子iframe 总结:iframe通信主要使用到了postMessage方法,使用方法为:otherWin...

  • react-native WebVIew消息传递

    onMessage在 webview 内部的网页中调用 window.postMessage 方法时可以触发此属性...

网友评论

    本文标题:postMessage 方法的小坑

    本文链接:https://www.haomeiwen.com/subject/kcpyzqtx.html