@eastgold15/vscode-webview
Version:
优化 webview 页面与 vscode 扩展之间的 postMessage 通信
1 lines • 8.77 kB
Source Map (JSON)
{"version":3,"file":"index.mjs","names":[],"sources":["../src/index.ts"],"sourcesContent":["import type { WebviewApi as VsCodeWebviewApi } from \"vscode-webview\";\n\nexport type PostMessageOptions = PostMessageAsyncOptions &\n PostMessageDataOptions;\n\nexport interface PostMessageAsyncOptions {\n /**\n * the millisecond of try interval time\n * @default 200\n */\n interval?: number;\n /**\n * the millisecond of post timeout\n * @default 10000\n */\n timeout?: number;\n}\n\nexport interface PostMessageDataOptions {\n /**\n * the name of data in the message, default 'data'\n */\n dataKey?: string;\n /**\n * the name of key in the message, default 'type'\n */\n typeKey?: string;\n}\n\nconst INTERVAL = 200;\nconst TIMEOUT = 10_000;\nconst TYPE_KEY = \"type\";\nconst DATA_KEY = \"data\";\n\nconst globalPostMessageOptions: PostMessageOptions = {\n dataKey: DATA_KEY,\n interval: INTERVAL,\n timeout: TIMEOUT,\n typeKey: TYPE_KEY,\n};\n\nfunction isNil(v: any) {\n return typeof v === \"undefined\" || v === null;\n}\n\nexport type PostMessageListener<T> = (data: T) => void | Promise<void>;\n\n/**\n * A utility wrapper around the acquireVsCodeApi() function, which enables\n * message passing and state management between the webview and extension\n * contexts.\n */\nexport class WebviewApi<StateType = any> {\n private readonly webviewApi!: VsCodeWebviewApi<StateType>;\n private _options: PostMessageOptions = {\n interval: INTERVAL,\n timeout: TIMEOUT,\n };\n\n private readonly listeners: Map<string | number, PostMessageListener<any>[]> =\n new Map();\n\n constructor(options?: PostMessageOptions) {\n if (typeof acquireVsCodeApi !== \"function\") {\n console.error(\"acquireVsCodeApi is not a function\");\n return;\n }\n\n this.setOptions(options || {});\n this.webviewApi = acquireVsCodeApi();\n\n window.addEventListener(\"message\", (event) => {\n const message = event.data || {};\n const { typeKey, dataKey } = this._options;\n this._runListener(\n message[typeKey ?? TYPE_KEY],\n message[dataKey ?? DATA_KEY]\n );\n });\n }\n\n /**\n * set the post message options\n * @param options\n */\n public setOptions(options: PostMessageOptions) {\n this._options = {\n ...globalPostMessageOptions,\n ...this._options,\n ...options,\n };\n }\n\n private _postMessage(\n type: string | number,\n data: any | undefined,\n options: PostMessageOptions\n ) {\n if (!this.webviewApi) {\n return;\n }\n\n this.webviewApi.postMessage({\n [options.typeKey ?? TYPE_KEY]: type,\n [options.dataKey ?? DATA_KEY]: data,\n });\n }\n\n private _runListener(type: string | number, result: any, error?: any) {\n if (isNil(type) || this.listeners.size === 0) {\n return;\n }\n const listeners = this.listeners.get(type);\n if (listeners) {\n if (!isNil(result)) {\n listeners[0]?.(result);\n }\n if (!isNil(error)) {\n listeners[1]?.(error);\n }\n }\n }\n\n /**\n * Post a message to the owner of the webview\n * @param type the message type\n * @param data the message content\n * @param options\n */\n\n public post(type: string | number, data: any | undefined) {\n this._postMessage(type, data, this._options);\n }\n\n /**\n * 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.\n * @param type the message type\n * @param data the message content\n * @param options\n */\n public postAndReceive<T>(\n type: string | number,\n data: any | undefined,\n options?: PostMessageAsyncOptions\n ): Promise<T> {\n return new Promise((resolve, reject) => {\n if (!this.webviewApi) {\n reject(new Error(\"acquireVsCodeApi is not available\"));\n return;\n }\n\n const opts = { ...this._options, ...options };\n const post = () => {\n this._postMessage(type, data, opts);\n };\n\n const intervalId = setInterval(post, opts.interval ?? INTERVAL);\n\n const _runListener = this._runListener;\n\n const timeoutId = setTimeout(() => {\n window.removeEventListener(\"message\", receive);\n clearInterval(intervalId);\n\n _runListener(type, undefined, new Error(\"Timeout\"));\n\n reject(new Error(\"Timeout\"));\n }, opts.timeout ?? TIMEOUT);\n\n function receive(e: MessageEvent<any>) {\n if (\n !(e.origin.startsWith(\"vscode-webview://\") && e.data) ||\n e.data[opts.typeKey ?? TYPE_KEY] !== type\n ) {\n return;\n }\n\n window.removeEventListener(\"message\", receive);\n clearTimeout(timeoutId);\n clearInterval(intervalId);\n\n const res = e.data[opts.dataKey ?? DATA_KEY];\n _runListener(type, res);\n resolve(res);\n }\n\n window.addEventListener(\"message\", receive);\n post();\n });\n }\n\n /**\n * Register a listener for a message type\n * @param type the message type\n * @param success the success listener\n * @param fail the fail listener\n */\n on<T>(\n type: string | number,\n success: PostMessageListener<T>,\n fail?: PostMessageListener<any>\n ) {\n this.listeners.set(type, fail ? [success, fail] : [success]);\n }\n\n /**\n * Remove a listener for a message type\n * @param type the message type\n */\n off(type: string | number) {\n this.listeners.delete(type);\n }\n\n /**\n * Post a message to the owner of the webview\n * @param message the message content\n */\n postMessage<T = any>(message: T) {\n this.webviewApi.postMessage(message);\n }\n\n /**\n * Get the persistent state stored for this webview.\n *\n * @return The current state or `undefined` if no state has been set.\n */\n getState(): StateType | undefined {\n return this.webviewApi.getState();\n }\n\n /**\n * Set the persistent state stored for this webview.\n *\n * @param newState New persisted state. This must be a JSON serializable object. Can be retrieved\n * using {@link getState}.\n *\n * @return The new state.\n */\n setState<T extends StateType | undefined>(newState: T): T {\n this.webviewApi.setState(newState);\n return newState;\n }\n}\n"],"mappings":"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"}