diff --git a/libs/src/modules/LSPlugin.Request.ts b/libs/src/modules/LSPlugin.Request.ts index 7868954812..b2ba039e98 100644 --- a/libs/src/modules/LSPlugin.Request.ts +++ b/libs/src/modules/LSPlugin.Request.ts @@ -3,6 +3,7 @@ import { EventEmitter } from 'eventemitter3' export type IRequestOptions = { url: string + abortable: boolean headers: Record method: 'GET' | 'POST' | 'PUT' | 'PATCH' | 'DELETE' data: Object | ArrayBuffer @@ -40,8 +41,11 @@ export class LSPluginRequestTask { this._client.once( genTaskCallbackType(this._requestId), (e) => { - // handle error - resolve(e) + if (e && e instanceof Error) { + reject(e) + } else { + resolve(e) + } } ) }) @@ -61,9 +65,17 @@ export class LSPluginRequestTask { } abort() { - if (this._aborted) return + if ( + !this._requestOptions.abortable || + this._aborted + ) return - // TODO: impl + this._client.ctx._execCallableAPI( + 'http_request_abort', + this._requestId + ) + + this._aborted = true } get promise(): Promise { @@ -83,7 +95,7 @@ export class LSPluginRequestTask { * A simple request client */ export class LSPluginRequest extends EventEmitter { - constructor(private ctx: LSPluginUser) { + constructor(private _ctx: LSPluginUser) { super() // request callback listener @@ -108,17 +120,26 @@ export class LSPluginRequest extends EventEmitter { ) } - _request(options: WithOptional, keyof Omit>): LSPluginRequestTask { + async _request, keyof Omit>>(options: T): + Promise ? LSPluginRequestTask : R> { const pid = this.ctx.baseInfo.id const { success, fail, final, ...requestOptions } = options const reqID = this.ctx.Experiments.invokeExperMethod('request', pid, requestOptions) - // TODO: impl const task = LSPluginRequest.createRequestTask( this.ctx.Request, - reqID, { success, fail, final } + reqID, options ) - return task + if (!requestOptions.abortable) { + return task.promise + } + + return task as any + } + + get ctx(): LSPluginUser { + return this._ctx } } \ No newline at end of file diff --git a/resources/package.json b/resources/package.json index 1a4bf7213c..2c13a3f115 100644 --- a/resources/package.json +++ b/resources/package.json @@ -37,7 +37,8 @@ "@sentry/electron": "2.5.1", "posthog-js": "1.10.2", "@logseq/rsapi": "0.0.20", - "electron-deeplink": "1.0.10" + "electron-deeplink": "1.0.10", + "abort-controller": "3.0.0" }, "devDependencies": { "@electron-forge/cli": "^6.0.0-beta.57", diff --git a/src/electron/electron/handler.cljs b/src/electron/electron/handler.cljs index 707b65569c..3c1adccd4b 100644 --- a/src/electron/electron/handler.cljs +++ b/src/electron/electron/handler.cljs @@ -8,6 +8,7 @@ ["os" :as os] ["diff-match-patch" :as google-diff] ["/electron/utils" :as js-utils] + ["abort-controller" :as AbortController] [electron.fs-watcher :as watcher] [electron.configs :as cfgs] [promesa.core :as p] @@ -368,8 +369,10 @@ (defmethod handle :uninstallMarketPlugin [_ [_ id]] (plugin/uninstall! id)) +(def *request-abort-signals (atom {})) + (defmethod handle :httpRequest [_ [_ _req-id opts]] - (let [{:keys [url method data returnType headers]} opts] + (let [{:keys [url abortable method data returnType headers]} opts] (when-let [[method type] (and (not (string/blank? url)) [(keyword (string/upper-case (or method "GET"))) (keyword (string/lower-case (or returnType "json")))])] @@ -378,7 +381,11 @@ :headers (and headers (bean/->js headers))} (merge (when (and (not (contains? #{:GET :HEAD} method)) data) ;; TODO: support type of arrayBuffer - {:body (js/JSON.stringify (bean/->js data))})))) + {:body (js/JSON.stringify (bean/->js data))}) + + (when-let [^js controller (and abortable (AbortController.))] + (swap! *request-abort-signals assoc _req-id controller) + {:signal (.-signal controller)})))) (p/then (fn [^js res] (case type :json @@ -393,7 +400,17 @@ :text (.text res)))) - (p/catch identity))))) + (p/catch + (fn [^js e] + ;; TODO: handle special cases + (throw e))) + (p/finally + (fn [] + (swap! *request-abort-signals dissoc _req-id))))))) + +(defmethod handle :httpRequestAbort [_ [_ _req-id]] + (when-let [^js controller (get @*request-abort-signals _req-id)] + (.abort controller))) (defmethod handle :quitAndInstall [] (.quitAndInstall autoUpdater)) diff --git a/src/main/logseq/api.cljs b/src/main/logseq/api.cljs index e377e3d58b..0dd75c62bf 100644 --- a/src/main/logseq/api.cljs +++ b/src/main/logseq/api.cljs @@ -820,9 +820,9 @@ (p/catch #(req-cb %))) req-id))) -(defn ^:export exper_abort_request +(defn ^:export http_request_abort [req-id] - nil) + (ipc/ipc :httpRequestAbort req-id)) ;; helpers (defn ^:export query_element_by_id