UNPKG

@tomjs/vscode-webview

Version:

Optimize the postMessage issue between webview page and vscode extension

167 lines (163 loc) 5.13 kB
"use strict";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;