Skip to content

unsubscribe() behaviour is sometimes random #328

@giordanocolombi

Description

@giordanocolombi

Hi All,

I've been working for few months on a community visualization and I'm using this library to render the code in Google Data Studio.

The problem that I'm having is that randomly the visualization doesn't appear, so I decide to have a deeper look to understand what is happening under the hood.

I find out that Google Data studio Works as a pub/sub system and an event listener is needed to get the data that is sent in a specific message.

So I debug the library and I discover interesting things that I will be listed below:

Scenario 1
If I run the following code to render the viz
if (isLocal) { drawViz(local.input); } else { subscribeToData(drawViz, { transform: objectTransform }); }
what I get in the console of the broswer, when I hit the url of my Google Data Studio report, is the following:

debug1

(unfortunately, I can't take a screenshot of the visualization because it contains sensitive information, but believe me, it is really cool :D )
what I do, I just add some console.log to the subscribeToData function to track what the code does.

So far so good, the visualization always appears and works well

If I use the presentation mode

present

I start to have problems. If I look at what happens in the terminal, after few minutes I get:
debug2

that means Google Data Studio keeps sending the same message on a regular basis and this triggers the drawViz function everytime. In my case, it represents a big problem. My visualization is dynamic that means there are filters to apply, there is a timeline to drag, there are buttons to click that means I can take actions that will change what is shown. Thus, everytime one message is sent, the dashboard is refreshed and I lose track of what I was looking at. Pretty bad, honestly.

Looking at the source code, I evenutally find in the docstring (I really want to stop and say thank you to take the time to write the comment, I can't even describe how precious it was to find it) a solution to stop receiving messages from google data studio by removing the event listener after a certain time using setTimeout. this leads us toward the Scenario 2.

Scenario 2

I then modify my code as it is suggested in the documentation:

if (isLocal) {
  drawViz(local.input);
} else {
  var unsubscribe = subscribeToData(drawViz, {
    transform: objectTransform,
  });
  // the timeout is needed to prevent the dashboard refresh in presentation mode
  setTimeout(function () {
    unsubscribe();
  }, 5000);
}

and by doing this, indeed, the problem in presentation mode is solved. Unfortunately a different one appears.

sometimes what I get is:
debug3

that is totally fine. Indeed, in order

  1. we add the event listener
  2. we get the message of type render
  3. we render the viz
  4. we remove the event listener to prevent subscribeTodata to be triggered again in the future

but sometimes what I get is:

debug4

that means the event listener is removed before the message is received and of course the visualization is not rendered and the dashboard appears empty. I try to increase/change the timeout (I can't really increase it too much, I would prefer to not wait 15+ seconds) but the behaviour still happens even with long timeout. It seems pretty random, and my understanding is that it is quite difficult to choose a specific timeout number that would work in any scenarios, also because I think the process is highly correlated with server latency, connection speed and broswer too (with Firefox for example it happens more often).

I thought a bit about the code and what we want to achieve and I came up with a solution that seems working better and solve the problem. Thus the subscribeToData function could be modified as below:

exports.subscribeToData = function (cb, options) {
  if (isValidTransform(options.transform)) {
    var onMessage_1 = function (message) {
      console.log('we receive a message', message);
      if (message.data.type === types_1.MessageType.RENDER) {
        cb(options.transform(message.data));
        window.removeEventListener('message', onMessage_1);
      } else {
        console.error(
          'MessageType: ' +
            message.data.type +
            ' is not supported by this version of the library.'
        );
      }
    };
    window.addEventListener('message', onMessage_1);
    var componentId = exports.getComponentId();
    // Tell DataStudio that the viz is ready to get events.
    var vizReadyMessage = {
      componentId: componentId,
      type: types_1.ToDSMessageType.VIZ_READY,
    };
    window.parent.postMessage(vizReadyMessage, '*');
  } else {
    throw new Error('Only the built in transform functions are supported.');
  }
};

so basically the idea would be to remove the event listener as soon as cb is invoked. In this case we would also avoid the usage of setTimeout and unsuscribe that, in my opinion, in this framework it doesn't work great.

Let me know what you think guys. I would be more than happy to open a PR with this little change

Best,
Giordano

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions