Skip to content

Understanding the Post Message Communication Flow

Michael Blythe edited this page Aug 30, 2016 · 5 revisions

Although powerbi-client is bundled as a single script for ease of use, there are 4 other dependent libraries that enable familiar Promise-based programming style for communication across windows:

  1. window-post-message-proxy
  2. http-post-message
  3. powerbi-models
  4. powerbi-router

Check out those repositories for individual descriptions and example usage.

In summary, we simulate HTTP protocol over window.postMessage. This makes reasoning about message structure intuitive for web developers instead of being another arbitrary protocol. This also makes understanding the flow just like any other client server relationship. Examples include:

  • Getting pages on a report: GET /report/pages
  • Getting visuals on a page: GET /report/pages/ReportSection/visuals

Sequence Diagram

There is more complexity in understanding the communication flow when the requests are state changing operations such as changing pages or setting filters. These operations can be initiated programmatically by the SDK or manually by the user, and in order to have a consistent way of dealing with this in code the APIs are asynchronous.

This means instead of request and response, it is commands and events.In the case of the SDK sending the command it will only be validated and immediately return 202 Accepted response. Meanwhile, the embed will execute the operation and when complete it will send an event. In the case of the user initiating the command, only the event will be emitted.

Page change example:

// Register event handler for page change events.
// Will execute regardless of the event being initiated programmatically or by the user.
report.on('pageChanged', event => {
  const page = event.detail.newPage;
  console.log(`${page.name} was set as active page`);
  // ... update ui with new page
});

// Programmatically change pages that will resolve before the page has actually changed.
page.setActive()
  .then(() => {
    console.log('command accepted');
  })
  .catch(errors => {
    console.log(errors);
  });