Spaces:
Running
Running
File size: 2,931 Bytes
5c05829 | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 | import { DEFAULT_TIMEOUT } from '../lib/constants'
import type RealtimeChannel from '../RealtimeChannel'
export default class Push {
sent: boolean = false
timeoutTimer: number | undefined = undefined
ref: string = ''
receivedResp: {
status: string
response: { [key: string]: any }
} | null = null
recHooks: {
status: string
callback: Function
}[] = []
refEvent: string | null = null
/**
* Initializes the Push
*
* @param channel The Channel
* @param event The event, for example `"phx_join"`
* @param payload The payload, for example `{user_id: 123}`
* @param timeout The push timeout in milliseconds
*/
constructor(
public channel: RealtimeChannel,
public event: string,
public payload: { [key: string]: any } = {},
public timeout: number = DEFAULT_TIMEOUT
) {}
resend(timeout: number) {
this.timeout = timeout
this._cancelRefEvent()
this.ref = ''
this.refEvent = null
this.receivedResp = null
this.sent = false
this.send()
}
send() {
if (this._hasReceived('timeout')) {
return
}
this.startTimeout()
this.sent = true
this.channel.socket.push({
topic: this.channel.topic,
event: this.event,
payload: this.payload,
ref: this.ref,
join_ref: this.channel._joinRef(),
})
}
updatePayload(payload: { [key: string]: any }): void {
this.payload = { ...this.payload, ...payload }
}
receive(status: string, callback: Function) {
if (this._hasReceived(status)) {
callback(this.receivedResp?.response)
}
this.recHooks.push({ status, callback })
return this
}
startTimeout() {
if (this.timeoutTimer) {
return
}
this.ref = this.channel.socket._makeRef()
this.refEvent = this.channel._replyEventName(this.ref)
const callback = (payload: any) => {
this._cancelRefEvent()
this._cancelTimeout()
this.receivedResp = payload
this._matchReceive(payload)
}
this.channel._on(this.refEvent, {}, callback)
this.timeoutTimer = <any>setTimeout(() => {
this.trigger('timeout', {})
}, this.timeout)
}
trigger(status: string, response: any) {
if (this.refEvent)
this.channel._trigger(this.refEvent, { status, response })
}
destroy() {
this._cancelRefEvent()
this._cancelTimeout()
}
private _cancelRefEvent() {
if (!this.refEvent) {
return
}
this.channel._off(this.refEvent, {})
}
private _cancelTimeout() {
clearTimeout(this.timeoutTimer)
this.timeoutTimer = undefined
}
private _matchReceive({
status,
response,
}: {
status: string
response: Function
}) {
this.recHooks
.filter((h) => h.status === status)
.forEach((h) => h.callback(response))
}
private _hasReceived(status: string) {
return this.receivedResp && this.receivedResp.status === status
}
}
|