In Visual Studio Code extension webviews you probably need to get familiar with post-messaging communication. This post-messaging communication is used when you want to start a process, request information, etc.
For this communication flow to work, the extension and webview can send and listen to incoming messages. Although this is not a complicated flow to understand, it quickly feels like a disconnected communication flow, as you cannot simply wait for a response.
To understand this “disconnected” communication flow better, let us take the following example: Once I open the webview, I want to show all the project files. The extension needs to process the data when I click on a file.
The whole communication flow looks as follows:
The disconnected experience explained
In the above example, the disconnected experience is in steps 1 and 2. You send a message, and the extension will perform an action based on the message received and sends back a message with the result.
infoDocumentation - Passing messages from an extension to a webview
Comparing this to an API, you wait for its response if you call an API to receive data.
In the extension/webview communication, you send a message, but you won’t get a response. You listen to messages coming back, making it a disconnected experience.
Creating this flow in code, it would look as follows:
|
|
This disconnection between messages sending from the webview to the extension and back made me wonder how to simplify it.
Simplify the communication flow
What I wanted to achieve was to have a similar experience as to calling APIs. You request data and wait for its response.
That is how I came up with the MessageHandler, which is nothing more than a wrapper around the post-message communication.
When requesting data with the message handler, it creates a callback function that returns a promise and identifies it with a requestId. The message sends this ID with the message command and payload to the extension listener.
See here a snippet of the class:
|
|
infoThe above code uses the
@estruyf/vscode
npm dependency, of which you can find the whole implementation here: MessageHandler.ts
In return, the message handler must wait until the extension sends a message with the same request ID.
When a message with the same request ID is received, the callback function gets executed, and the promise resolves (or gets rejected in case of an issue).
Using the message handler in the webview
With the message handler, sending or requesting data from the webview is straightforward.
|
|
Changes on the extension level
On the extension level, you do not have to change much. All you need to do is add the requestId property with the ID that was passed with the message and post the new message.
|
|
The requestId property is what the message handler uses as the identifier returning the response data.
|
|
Sample project
In the Visual Studio Code Extension - React Webview Starter repository, you can find an example of how this whole message handling system works.