mirror of
https://github.com/logseq/logseq.git
synced 2026-04-25 22:54:48 +00:00
145 lines
3.2 KiB
TypeScript
145 lines
3.2 KiB
TypeScript
import { LSPluginUser, WithOptional } from '../LSPlugin.user'
|
|
import { EventEmitter } from 'eventemitter3'
|
|
|
|
export type IRequestOptions<R = any> = {
|
|
url: string
|
|
abortable: boolean
|
|
headers: Record<string, string>
|
|
method: 'GET' | 'POST' | 'PUT' | 'PATCH' | 'DELETE'
|
|
data: Object | ArrayBuffer
|
|
timeout: number
|
|
returnType: 'json' | 'text' | 'base64' | 'arraybuffer'
|
|
success: (result: R) => void
|
|
fail: (err: any) => void
|
|
final: () => void
|
|
}
|
|
|
|
export type RequestTaskID = string | number
|
|
|
|
const CLIENT_MSG_CALLBACK = '#lsp#request#callback'
|
|
const genTaskCallbackType = (id: RequestTaskID) => `task_callback_${id}`
|
|
|
|
/**
|
|
* Request task
|
|
*/
|
|
export class LSPluginRequestTask<R = any> {
|
|
private readonly _promise: Promise<R>
|
|
private _aborted: boolean = false
|
|
|
|
constructor(
|
|
private _client: LSPluginRequest,
|
|
private _requestId: RequestTaskID,
|
|
private _requestOptions: Partial<IRequestOptions> = {}
|
|
) {
|
|
|
|
this._promise = new Promise<any>((resolve, reject) => {
|
|
if (!this._requestId) {
|
|
return reject(null)
|
|
}
|
|
|
|
// task result listener
|
|
this._client.once(
|
|
genTaskCallbackType(this._requestId),
|
|
(e) => {
|
|
if (e && e instanceof Error) {
|
|
reject(e)
|
|
} else {
|
|
resolve(e)
|
|
}
|
|
}
|
|
)
|
|
})
|
|
|
|
const { success, fail, final } = this._requestOptions
|
|
|
|
this._promise
|
|
.then((res) => {
|
|
success?.(res)
|
|
})
|
|
.catch((e) => {
|
|
fail?.(e)
|
|
})
|
|
.finally(() => {
|
|
final?.()
|
|
})
|
|
}
|
|
|
|
abort() {
|
|
if (
|
|
!this._requestOptions.abortable ||
|
|
this._aborted
|
|
) return
|
|
|
|
this._client.ctx._execCallableAPI(
|
|
'http_request_abort',
|
|
this._requestId
|
|
)
|
|
|
|
this._aborted = true
|
|
}
|
|
|
|
get promise(): Promise<R> {
|
|
return this._promise
|
|
}
|
|
|
|
get client(): LSPluginRequest {
|
|
return this._client
|
|
}
|
|
|
|
get requestId(): RequestTaskID {
|
|
return this._requestId
|
|
}
|
|
}
|
|
|
|
/**
|
|
* A simple request client
|
|
*/
|
|
export class LSPluginRequest extends EventEmitter {
|
|
constructor(private _ctx: LSPluginUser) {
|
|
super()
|
|
|
|
// request callback listener
|
|
this.ctx.caller.on(
|
|
CLIENT_MSG_CALLBACK,
|
|
(e: any) => {
|
|
const reqId = e?.requestId
|
|
if (!reqId) return
|
|
|
|
this.emit(genTaskCallbackType(reqId), e?.payload)
|
|
}
|
|
)
|
|
}
|
|
|
|
static createRequestTask(
|
|
client: LSPluginRequest,
|
|
requestID: RequestTaskID,
|
|
requestOptions: Partial<IRequestOptions>
|
|
) {
|
|
return new LSPluginRequestTask(
|
|
client, requestID, requestOptions
|
|
)
|
|
}
|
|
|
|
async _request<R extends {},
|
|
T extends WithOptional<IRequestOptions<R>, keyof Omit<IRequestOptions, 'url'>>>(options: T):
|
|
Promise<T extends Pick<IRequestOptions, 'abortable'> ? LSPluginRequestTask<R> : R> {
|
|
const pid = this.ctx.baseInfo.id
|
|
const { success, fail, final, ...requestOptions } = options
|
|
const reqID = this.ctx.Experiments.invokeExperMethod('request', pid, requestOptions)
|
|
|
|
const task = LSPluginRequest.createRequestTask(
|
|
this.ctx.Request,
|
|
reqID, options
|
|
)
|
|
|
|
if (!requestOptions.abortable) {
|
|
return task.promise
|
|
}
|
|
|
|
return task as any
|
|
}
|
|
|
|
get ctx(): LSPluginUser {
|
|
return this._ctx
|
|
}
|
|
} |