background

Access to 3D model in the project, because the 3D model team only provides iframe access, postMessage communication and communication data format.

// The interface for the API call
// params passes parameters
{
    require: {
        api: Strubg,
        params: *}}Copy the code

The way we started

   <div class="model">
       <iframe src="xxx" ref="iframe" />
   </div>
Copy the code
created() {
    this.initEvent()
},
methods: {
    initEvent() {
        window.addEventListener(
        'message'.this.handleReceive,
        false
      )

      this.$once('hook:beforeDestroy'.() = > {
        window.removeEventListener(
          'message'.this.handleReceive,
          false)})},// Receive events
    handleReceive(e) {
        console.log(e)
        // e.data is the received data
    },
    // Send events
    postMessage({ api, params }) {
        const mergeParams = {
            require: {
                api,
                params
            }
        }
        this.$refs.iframe.contentWindow.postMessage(mergeParams, The '*')}}Copy the code
// When used
this.postMessage({
    api: 'setData'
})
Copy the code

You can’t get the return value directly from the call interface. You can only get the return value through handleReceive and call it back.

Promise transformation

Train of thought to sort out

Uuid needs to be agreed with the 3D modeling team.

// queue.js
/** * asynchronous queue *@param time- Timeout duration, in seconds */
export default class QueuePromise {
  constructor(time = 15) {
    this.queue = new Map(a)this.time = time
  }

  // Join the queue
  push(uuid, resolve, reject) {
    const params = { uuid, resolve, reject }
    params.timer = setTimeout(() = > {
      this.put(uuid)
      reject({ code: -1.msg: 'timeout'})},this.time * 1000)
    this.queue.set(uuid, params)
  }

  // Execute queue and unstack
  perform(uuid, params) {
    const apiQueue = this.put(uuid)
    // Execute resolve and return the result
    apiQueue.resolve(params)
  }

  // Find and unstack
  put(uuid) {
    const apiQueue = this.queue.get(uuid)
    if(! apiQueue)return
    this.queue.delete(uuid)
    apiQueue.timer && clearTimeout(apiQueue.timer)
    return apiQueue
  }

  clear() {
    this.queue.forEach(e= > {
      e.timer && clearTimeout(e.timer)
    })
    this.queue = null}}Copy the code
+ import Queue from './queue'

created() {
    this.initEvent()
},
methods: {
    initEvent() {
+ this.queue = new Queue()
        window.addEventListener(
            'message',
            this.handleReceive,
            false
        )

      this.$once('hook:beforeDestroy', () => {
        window.removeEventListener(
          'message',
          this.handleReceive,
          false
        )
+ this.queue && this.queue.clear()})}, // Receive events handleReceive(e) {console.log(e) // e.ata is the received data+ const { api, params, uuid } = e.data? .require || {}
+ if (uuid) return this.queue.perform(uuid, params) // Resolve or reject if uuid existsPostMessage ({API, params}) {+ return new Promise((resolve, reject) => {
            const mergeParams = {
                require: {
                    api,
                    params
                }
            }
+ this.$refs.iframe.contentWindow.postMessage(mergeParams, '*')
+ this.queue.push(objRequest.require.uuid, resolve, reject)
+})}}Copy the code
// When used
this.postMessage({
    api: 'setData'
}).then(e= > { // Get the return value
    console.log(e)
})

/ / or
const res = await this.postMessage({
    api: 'setData'
})
Copy the code

So that’s how postMessage promises.