@tomjs/vscode-webview
Version:
Optimize the postMessage issue between webview page and vscode extension
167 lines (163 loc) • 5.13 kB
JavaScript
;Object.defineProperty(exports, "__esModule", {value: true});var __defProp = Object.defineProperty;
var __defNormalProp = (obj, key, value) => key in obj ? __defProp(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
var __publicField = (obj, key, value) => __defNormalProp(obj, typeof key !== "symbol" ? key + "" : key, value);
// src/index.ts
var INTERVAL = 200;
var TIMEOUT = 1e4;
var TYPE_KEY = "type";
var DATA_KEY = "data";
var globalPostMessageOptions = {
interval: INTERVAL,
timeout: TIMEOUT,
typeKey: TYPE_KEY,
dataKey: DATA_KEY
};
function isNil(v) {
return typeof v === "undefined" || v === null;
}
var WebviewApi = class {
constructor(options) {
__publicField(this, "webviewApi");
__publicField(this, "_options", {
interval: INTERVAL,
timeout: TIMEOUT
});
__publicField(this, "listeners", /* @__PURE__ */ new Map());
if (typeof acquireVsCodeApi !== "function") {
console.error("acquireVsCodeApi is not a function");
return;
}
this.setOptions(options || {});
this.webviewApi = acquireVsCodeApi();
window.addEventListener("message", (event) => {
const message = event.data || {};
const { typeKey, dataKey } = this._options;
this._runListener(message[typeKey != null ? typeKey : TYPE_KEY], message[dataKey != null ? dataKey : DATA_KEY]);
});
}
/**
* set the post message options
* @param options
*/
setOptions(options) {
this._options = Object.assign({}, globalPostMessageOptions, this._options, options);
}
_postMessage(type, data, options) {
var _a, _b;
if (!this.webviewApi) {
return;
}
this.webviewApi.postMessage({
[(_a = options.typeKey) != null ? _a : TYPE_KEY]: type,
[(_b = options.dataKey) != null ? _b : DATA_KEY]: data
});
}
_runListener(type, result, error) {
if (isNil(type) || this.listeners.size === 0) {
return;
}
const listeners = this.listeners.get(type);
if (listeners) {
if (!isNil(result)) {
listeners[0] && listeners[0](result);
}
if (!isNil(error)) {
listeners[1] && listeners[1](error);
}
}
}
/**
* Post a message to the owner of the webview
* @param type the message type
* @param data the message content
* @param options
*/
post(type, data) {
this._postMessage(type, data, this._options);
}
/**
* Post a message to the owner of the webview, and return the response. The type of the message to be sent and received must be the same.
* @param type the message type
* @param data the message content
* @param options
* @returns
*/
postAndReceive(type, data, options) {
return new Promise((resolve, reject) => {
var _a, _b;
if (!this.webviewApi) {
reject(new Error("acquireVsCodeApi is not available"));
return;
}
const opts = Object.assign({}, this._options, options);
const post = () => {
this._postMessage(type, data, opts);
};
const intervalId = setInterval(post, (_a = opts.interval) != null ? _a : INTERVAL);
const timeoutId = setTimeout(() => {
window.removeEventListener("message", receive);
clearInterval(intervalId);
this._runListener(type, void 0, new Error("Timeout"));
reject(new Error("Timeout"));
}, (_b = opts.timeout) != null ? _b : TIMEOUT);
const receive = (e) => {
var _a2, _b2;
if (!e.origin.startsWith("vscode-webview://") || !e.data || e.data[(_a2 = opts.typeKey) != null ? _a2 : TYPE_KEY] !== type) {
return;
}
window.removeEventListener("message", receive);
clearTimeout(timeoutId);
clearInterval(intervalId);
const res = e.data[(_b2 = opts.dataKey) != null ? _b2 : DATA_KEY];
this._runListener(type, res);
resolve(res);
};
window.addEventListener("message", receive);
post();
});
}
/**
* Register a listener for a message type
* @param type the message type
* @param success the success listener
* @param fail the fail listener
*/
on(type, success, fail) {
this.listeners.set(type, fail ? [success, fail] : [success]);
}
/**
* Remove a listener for a message type
* @param type the message type
*/
off(type) {
this.listeners.delete(type);
}
/**
* Post a message to the owner of the webview
* @param message the message content
*/
postMessage(message) {
this.webviewApi.postMessage(message);
}
/**
* Get the persistent state stored for this webview.
*
* @return The current state or `undefined` if no state has been set.
*/
getState() {
return this.webviewApi.getState();
}
/**
* Set the persistent state stored for this webview.
*
* @param newState New persisted state. This must be a JSON serializable object. Can be retrieved
* using {@link getState}.
*
* @return The new state.
*/
setState(newState) {
this.webviewApi.setState(newState);
return newState;
}
};
exports.WebviewApi = WebviewApi;