async _asyncloadExternalRefs (schema, fetchUrl, fileBase, firstIteration = false) {
    const refs = this._getExternalRefs(schema, fetchUrl, firstIteration)
    let waiting = 0
    // Loop into all schema references
    for (const uri of Object.keys(refs)) {
      if (typeof uri === 'undefined') continue
      if (this.refs[uri]) continue
      if (this._isUniformResourceName(uri)) {
        this.refs[uri] = 'loading'
        waiting++
        const urnResolver = this.options.urn_resolver
        let urn = uri
        if (typeof urnResolver !== 'function') {
          // eslint-disable-next-line no-console
          console.log(`No "urn_resolver" callback defined to resolve "${urn}"`)
          throw new Error(`Must set urn_resolver option to a callback to resolve ${urn}`)
        }
        // theoretically a URN can contain a JSON pointer
        if (urn.indexOf('#') > 0) urn = urn.substr(0, urn.indexOf('#'))
        let response
        try {
          let externalSchema
          response = await urnResolver(urn)
          try {
            externalSchema = JSON.parse(response)
          } catch (e) {
            // eslint-disable-next-line no-console
            console.log(e)
            throw new Error(`Failed to parse external ref ${urn}`)
          }
          if (!(typeof externalSchema === 'boolean' || typeof externalSchema === 'object') || externalSchema === null || Array.isArray(externalSchema)) {
            throw new Error(`External ref does not contain a valid schema - ${urn}`)
          }

          this.refs[uri] = externalSchema

          await this._asyncloadExternalRefs(externalSchema, uri, fileBase)
        } catch (e) {
          // eslint-disable-next-line no-console
          console.log(e)
          throw new Error(`Failed to parse external ref ${urn}`)
        }

        if (typeof response === 'boolean') {
          throw new Error(`External ref does not contain a valid schema - ${urn}`)
        }
        continue
      }
      if (!this.options.ajax) throw new Error(`Must set ajax option to true to load external ref ${uri}`)
      waiting++

      let url = this._joinUrl(uri, fileBase)

      let externalSchema
      if (this.options.ajax_cache_responses) {
        const schemaFromCache = this.cacheGet(url)
        if (schemaFromCache) {
          externalSchema = schemaFromCache
        }
      }

      if (!externalSchema) {
        const response = await new Promise(resolve => {
          const r = new XMLHttpRequest()
          if (this.options.ajaxCredentials) r.withCredentials = this.options.ajaxCredentials
          r.overrideMimeType('application/json')
          r.open('GET', url, true)
          r.onload = () => {
            resolve(r)
          }
          r.onerror = (e) => {
            resolve(undefined)
          }
          r.send()
        })
        if (typeof response === 'undefined') throw new Error(`Failed to fetch ref via ajax - ${uri}`)
        try {
          externalSchema = JSON.parse(response.responseText)

          this.onSchemaLoaded({
            schema: externalSchema,
            schemaUrl: url
          })

          if (this.options.ajax_cache_responses) {
            this.cacheSet(url, externalSchema)
          }
        } catch (e) {
          // eslint-disable-next-line no-console
          console.log(e)
          throw new Error(`Failed to parse external ref ${url}`)
        }
      }

      if (!(typeof externalSchema === 'boolean' || typeof externalSchema === 'object') || externalSchema === null || Array.isArray(externalSchema)) {
        throw new Error(`External ref does not contain a valid schema - ${url}`)
      }
      this.refs[uri] = externalSchema
      const newfileBase = this._getFileBaseFromFileLocation(url)

      // Add leading slash.
      if (url !== uri) {
        const pathItems = url.split('/')
        url = (uri.substr(0, 1) === '/' ? '/' : '') + pathItems.pop()
      }
      await this._asyncloadExternalRefs(externalSchema, url, newfileBase)
    }

    if (!waiting) {
      return true
    }

    this.onAllSchemasLoaded()
  }
Loads external references via AJAX.

Will fail if this.options.ajax is not set to true.

@param {object} schema - JSON Schema with external references.
@param {string} fetchUrl - Base path from which to store the definitions.
  Typically the URI of the schema.
@param {string} fileBase - The base URL from which to load relative paths.
  Typically the URI of the schema minus filename, with trailing slash.
@param {boolean} firstIteration - Is it the first time we load this function? Help making difference between external ref vs internal pointer

@return {boolean}
@throws Error