constructor (
    config,
    protocolSupplier = detectWebPageProtocol,
    socketFactory = url => new WebSocket(url)
  ) {
    this._open = true
    this._pending = []
    this._error = null
    this._handleConnectionError = this._handleConnectionError.bind(this)
    this._config = config
    this._receiveTimeout = null
    this._receiveTimeoutStarted = false
    this._receiveTimeoutId = null
    this._closingPromise = null

    const { scheme, error } = determineWebSocketScheme(config, protocolSupplier)
    if (error) {
      this._error = error
      return
    }

    this._ws = createWebSocket(scheme, config.address, socketFactory)
    this._ws.binaryType = 'arraybuffer'

    const self = this
    // All connection errors are not sent to the error handler
    // we must also check for dirty close calls
    this._ws.onclose = function (e) {
      if (e && !e.wasClean) {
        self._handleConnectionError()
      }
      self._open = false
    }
    this._ws.onopen = function () {
      // Connected! Cancel the connection timeout
      self._clearConnectionTimeout()

      // Drain all pending messages
      const pending = self._pending
      self._pending = null
      for (let i = 0; i < pending.length; i++) {
        self.write(pending[i])
      }
    }
    this._ws.onmessage = event => {
      this._resetTimeout()
      if (self.onmessage) {
        const b = new ChannelBuffer(event.data)
        self.onmessage(b)
      }
    }

    this._ws.onerror = this._handleConnectionError

    this._connectionTimeoutFired = false
    this._connectionTimeoutId = this._setupConnectionTimeout()
  }
Create new instance
@param {ChannelConfig} config - configuration for this channel.
@param {function(): string} protocolSupplier - function that detects protocol of the web page. Should only be used in tests.