Skip to content

Multi-language Client Implementation

Below are WebSocket client implementation examples for various programming languages to connect and call iClick API.

Note

All examples implement the same functionality:

  • WebSocket connection and auto-reconnect
  • Request/response matching (based on evtid)
  • Timeout handling
  • Binary data support
  • Event push handling

Warning

The following code examples may not be fully verified and are for reference and learning purposes only. Please ensure thorough testing and validation before using in production environments.

javascript
const wserverPort = 23188
const wsevents = {}
let wsclient = null
let reconnectTimer = null

export function reconnect() {
    if( reconnectTimer || wsclient?.readyState === WebSocket.CONNECTING ){
        return
    }
    reconnectTimer = setTimeout(() => {
        console.log('API service reconnecting...')
        connectServer().finally(() => reconnectTimer = null)
    }, 1000 * 3)
}

export function connectServer() {
    return new Promise((_resolve) => {
        
        if( wsclient ){
            return
        }

        wsclient = new WebSocket(`ws://127.0.0.1:${wserverPort}`)
        wsclient.binaryType = 'arraybuffer'

        wsclient.onopen = () => {
            console.log('API service connected successfully')
            _resolve()
        }

        wsclient.onmessage = (_message) => {
     
            let _payload = _message.data,
                _bindata = null

            if( typeof _payload === 'string' ){

                _payload = JSON.parse(_payload)

            }else{

                // Some interfaces return binary data, need to parse [metaDataLength][metaData][binary]
                const _decoder = new TextDecoder('utf-8')   
                const _metaLength = _decoder.decode(_payload.slice(0, 6))
                                    _bindata = _payload.slice(6 + parseInt(_metaLength))
                                    _payload = JSON.parse(_decoder.decode(_payload.slice(6, 6 + parseInt(_metaLength))))
                _payload.data = _bindata
                _bindata = null
            }
            
            const _eventId = _payload.evtid
            const _event = wsevents[ _eventId ]
  
            if( _event ){

                if( _payload.type === 'error' ){
                    _event.reject(new Error(_payload.error))
                }else{
                    _event.resolve( _payload.data )
                }

                delete wsevents[ _eventId ]

            }else if( _payload.event ){

                // You can dispatch events according to different languages
            }
        }
        
        wsclient.onclose = (code) => {

            wsclient = null
            console.log('API service connection closed:', code)
            reconnect()
        }
        
        wsclient.onerror = (err) => {
            console.error('API service connection error:', err)
        }
    })
}


export function apiInvoke(type, _params = {}, _timeout = 18) {

    return new Promise((resolve, reject) => {

        if( !wsclient || wsclient.readyState !== WebSocket.OPEN ){

            reject( new Error('API service connection not ready') )

        }else{

            const _eventId = Math.random().toString(36).substring(2, 12)
            const _payload = {
                ..._params,
                type,
                evtid: _eventId,
                timeout: _timeout
            }

            wsevents[_payload.evtid] = { resolve, reject }

            wsclient.send(JSON.stringify(_payload))

            if( _timeout > 0 ){
                setTimeout(() => {

                    reject(new Error(`API service: ${_payload.evtid} Invoke Timeout !`))

                    delete wsevents[_payload.evtid]

                }, _timeout * 1000)
            }
        }
    })
}

// Usage example
await connectServer()
const result = await apiInvoke('click', { x: 100, y: 200, deviceId: 'XXXXXXXXXX' })

Next Steps

  • Read more specific API usage examples

Cooperation: try.catch@foxmail.com