-
Notifications
You must be signed in to change notification settings - Fork 147
Open
Labels
enhancementNew feature or requestNew feature or request
Description
Describe the feature
Why
Nowadays, many ai services are provided by http api, the task normally cost long time, http short polling is a simple way to get the result. For example: https://platform.tripo3d.ai/docs/task#polling
Solution
I previous implement it like following:
import EventEmitter from 'events'
import { omit } from 'lodash-es'
import type { Promisable } from 'type-fest'
interface EventData<D extends Record<string, any> = {}> {
start: void
response: D
error: any
stop: void
}
type Event = keyof EventData
type Options = RequestInit & {
interval?: number
pollingTimeout?: number
}
/**
* Http Short Polling
*/
export class HttpShortPoll<D> extends EventEmitter {
url: string
status: 'init' | 'polling' | 'stopped' = 'init'
_pollingTimer: NodeJS.Timeout | null = null
_startTimestamp: number | null = null
options: Options = {
interval: 1000,
// 20 minutes
pollingTimeout: 1000 * 60 * 20,
}
constructor(url: string, options?: Options) {
super()
this.url = url
this.options = { ...this.options, ...options }
}
on<E extends Event>(event: E, listener: (data: EventData<D>[E]) => Promisable<void>) {
return super.on(event, listener)
}
emit<E extends Event>(event: E, data?: EventData<D>[E]) {
return super.emit(event, data)
}
start() {
if (this.status !== 'init') {
return
}
this.status = 'polling'
this.emit('start')
this._startTimestamp = Date.now()
this._pollingTimer = setInterval(async () => {
if (this.status !== 'polling') {
return
}
if (Date.now() - this._startTimestamp > this.options.pollingTimeout) {
this.stop()
return
}
try {
const resp = await fetch(this.url, omit(this.options, ['interval', 'pollingTimeout']))
const json = await resp.json()
this.emit('response', json as D)
} catch (error) {
console.error(error)
this.emit('error', error)
return
}
}, this.options.interval)
}
stop() {
this.status = 'stopped'
if (this._pollingTimer) {
clearInterval(this._pollingTimer)
this._pollingTimer = null
}
this.emit('stop')
}
}
// for example
const poll = new HttpShortPoll('https://api.example.com/data', {
interval: 1000,
pollingTimeout: 10000,
})
poll.on('start', () => {
console.log('Polling started')
})
poll.on('response', (data) => {
console.log('Data received:', data)
})
poll.on('error', (error) => {
console.error('Error:', error)
})
poll.on('stop', () => {
console.log('Polling stopped')
})Additional information
- Would you be willing to help implement this feature?
Metadata
Metadata
Assignees
Labels
enhancementNew feature or requestNew feature or request