PostMessage with multiple functions or custom callbacks

前端 未结 4 1045
刺人心
刺人心 2021-02-05 08:17

So far I\'ve only seen tutorials for postmessage where one window sends a single kind of message, and the other window interprets the message in only a single way.

What

4条回答
  •  半阙折子戏
    2021-02-05 08:30

    Callbacks with postMessage: very possible and very useful

    There is a nice plugin I've found on npm called "silver-bullet". It does postMessage with callbacks and uses eventEmitter to get specific events as well. Its very nice.

    But to implement this I would do something like...

    phostMessage(iframe, someObj, callback);
    

    You have to do this:

    1. You need a common callback ID passed between frames communicating.
    2. The sender creates a unique callback ID on each message and stores it in a callback lookup hash to find the callback after sending.
    3. The receiver of the message only ensures the callback ID is sent back.
    4. All frames communicating use the same JS library for this.

    Here's a very basic demonstration of that:

    var callbacks = {};
    
    // when receiving messages
    window.addEventListener('message', function(ev) {
      // todo: add origin check
      if (!ev.data)
        return;
    
      var message;
      try {
        message = JSON.parse(ev.data);
      } catch (ex) {
        console.error(ex);
      }
    
      // ignore messages not having a callback ID
      if (!message || !message.callbackId)
        return;
    
      // we are the sender getting the callback
      if (callbacks[message.callbackId]) {
        callbacks[message.callbackId](message);
        delete callbacks[message.callbackId];
        return;
      }
    
      // we are the receiver so we respond with the callback ID
      // todo: restrict who can receive message (last param)
      iframe.contentWindow.postMessage(JSON.stringify(message), '*');
    });
    
    // when sending messages
    function phostMessage(iframe, obj, callback) {
      obj.eventId = Math.random();
      callbacks[obj.eventId] = callback;
      // todo: restrict who can receive message (last param)
      iframe.contentWindow.postMessage(JSON.stringify(obj), '*');
    }
    

    I take this concept a bit further and use a message handler lookup where the message has the desired handler function name to evoke and pass a message to. The message handler takes a callback as well that when completed fires the callback. The callback just has the simple logic of calling the native post message again sending back its received callback id.

    So the last line of code for the message event handling would be:

    if (messageHandler[message.handler])
      messageHandler[message.handler](message, function() {
        iframe.contentWindow.postMessage(JSON.stringify(message), '*');
      });
    else
      iframe.contentWindow.postMessage(JSON.stringify(message), '*');
    

    which allows asynchronous stuff to happen.

提交回复
热议问题