postMessage: communication between browser tabs
Ever wondered how could one tab opens up another tab and they communicate with each other? Maybe you go to buy something on some site, now that site might open a new tab for processing your payment and if you try going back to the first tab/main site, you would see that the page has some sort of timer running. How does that page know that you have or have not completed the payment yet? That too which is taking place in other tab? How do these two tab communicate with each other? The answer is using postMessage
browser API and message
event listener.
What’s happening here is that your main site is opening the payment page in a new tab mostly using window.open()
method. How will the new tab refer to the main tab which opened it? You can refer that window using window.opener
. As the name suggests, it simply points to the window object which caused this new tab to open. Main site would have started some sort of timer as soon as this new page is opened, saying something like Please complete the transaction in 5:00 minutes
or so.
Your new tab obviously knows if you’re done with the payment or not. Now once you complete the payment on this tab, main site should know that. Here comes the interesting part of postMessage
. This new tab will post a message
to the window which opened it, using postMessage
API, indicating that the payment is now complete. Okay, this tab has done its job, but how does the main site get to know this?
There’s an event called message
which this main site would be listening to (just like how we listen to click
events). As soon as the main site receives the message
which contains valid payload/data of the payment being completed, the UI would redirect you to maybe tracking details of that particular thing.
Enough of theory, right? Let’s get coding!
Here’s our index.html
, nothing fancy going on here. Just one button and simple text. Do focus on the span though, we’re going to play with it 😉
This is what we see:
Here’s the corresponding JavaScript code. Clicking on the button should disable it and a new tab should open with payment.html
Now we need to know how the payment.html
looks like, right? Just one single button to replicate the behaviour as if the user has completed the payment (over-simplification 😬)
Here’s what this HTML renders:
Here’s the corresponding JavaScript code. On clicking the button, we’re sending a postMessage
to the window.opener
with the payload which confirms that the payment has completed. Finally we close this tab.
But hey! How does our main page get to know that the payment has succeeded? We haven’t written any logic for it yet! Let’s add that to our index.js
Now we have added an event listener for message
event. Once the user clicks on the button on the other tab, we’re triggering a message, right? As soon as this tab receives a message, it opens up the e
or event
object and looks inside it for data.isPaymentCompleted
. Once that’s done, we know the user has completed their payment and we modify the UI content. Remember we had talked about the span
earlier? We’re now making it’s textContent
to be true 😉
Here is the hosted demo: https://swaraj-postmessage-demo.netlify.app. Here’s the GitHub repo if you want to have a look: https://github.com/swarajpure/postMessage-demo
This might not have been a very good example, since we shouldn’t be dependent only on frontend for functionalities which are as delicate as payments, we should have checks from backend as well. Nonetheless, I guess you get the point I was trying to make and hope that you would have learnt something new 😄
Thank you! 🎉