Конструктор класса Javascript не устанавливает переменные класса, как ожидалось

#javascript #class-constructors

#javascript #конструкторы классов

Вопрос:

Я пытаюсь установить конечные точки API по среде в вспомогательном классе javascript, который я использую для извлечения данных в мое приложение react. Это выглядит так:

 import axios from 'axios';

class QueryHelper {
    endpoints;
    SupportEndpoint;
    MemberEndpoint;

    constructor() {
        debugger
        // get the endpoints set
        fetch('/environment')
            .then(response => response.json())
            .then(data => this.endpoints = data) // set the endpoints var with the json payload with all the endpoint and env data
            .then(() => {
                this.SupportEndpoint = this.endpoints.supportBaseUrl;
                this.MemberEndpoint = this.endpoints.memberBaseUrl;
            });
    }

    
    async fetchData(resource) {
        const resp = await axios.get(this.SupportEndpoint   '/'   resource);
        return resp.data;
    }
}

export default QueryHelper;
  

Он будет использоваться следующим образом:

 let helper = new QueryHelper();
helper.fetchData('MemberProfile')
    .then(response => response.json())
    .then(//do some other stuff);
  

Когда я нажимаю точку останова, я могу пройти через конструктор, и различные конечные точки, похоже, устанавливаются так, как ожидалось. Но когда fetchData вызывается метод SupportEndpoint (и любая другая конечная точка) undefined , и вызов ajax завершается с ошибкой 404.

Комментарии:

1. fetch это асинхронная операция и возвращает обещание, поэтому вам нужно дождаться ее завершения. Не уверен, почему вы используете axios и fetch в своем коде.

Ответ №1:

Конструктор асинхронно устанавливает эти реквизиты. Можно подождать до fetch("/environment") разрешения, а затем вызвать helper.fetchData() , но если вы вызовете его слишком рано после создания экземпляра, то произойдет сбой.

Вам нужен какой-то механизм для обеспечения помощника isRready .

 function defer() {
    let resolve, reject;
    const promise = new Promise((r, j) => {
        resolve = r;
        reject = j;
    });
    return { resolve, reject, promise };
}

class QueryHelper {
    endpoints;
    SupportEndpoint;
    MemberEndpoint;

    _isReady;
    _d;
    get isReady() {
        if (this._isReady) return Promise.resolve(true);
        if (!this._d) {
            this._d = defer();
        }
        return this._d.promise;
    }

    constructor() {
        fetch('/environment')
            .then(response => response.json())
            .then(data => this.endpoints = data) // set the endpoints var with the json payload with all the endpoint and env data
            .then(() => {
                this.SupportEndpoint = this.endpoints.supportBaseUrl;
                this.MemberEndpoint = this.endpoints.memberBaseUrl;
                this._isReady = true;
                if (this._d amp;amp; this._d.resolve) this._d.resolve(true);
            });
    }

    
    async fetchData(resource) {
        await this.isReady;
        const resp = await axios.get(this.SupportEndpoint   '/'   resource);
        return resp.data;
    }
}