Подписка RxJS и локальная переменная - пустая проблема - PullRequest
0 голосов
/ 20 сентября 2018

Я написал эту функцию в своем приложении Angular для вызова службы RESTful, класс находится за пределами компонента в качестве класса обслуживания

getProducts(): IProduct[] {
    let productsObservable = this.http.get<IProduct[]>(this.productUrl).pipe(
        tap(data => console.log("All: " + JSON.stringify(data))),
        catchError(this.serviceErrorHandler)
    );

    let products: IProduct[];
    let errorMessage: string = "";

    productsObservable.subscribe(
        p => {
            products = p;
            console.log("All in subscribe: " + JSON.stringify(products));
        },
        error => errorMessage = <any>error
    );

    if (errorMessage.length > 0) {
        console.log(errorMessage);
        throw new Error(errorMessage);
    }

    console.log("All before return: " + JSON.stringify(products));
    return products;
}

У меня есть 3 строки кода с console.log для отслеживания моегоdata.

  • В первой функции tap все данные JSON отображаются в консоли, это означает, что вызов службы выполнен успешно.
  • Второй в моей функции subscribeтакже отображает полезную нагрузку JSON.
  • Но последняя не удалась.Я установил точку останова для функции журнала консоли списка и обнаружил, что переменная products равна нулю.

Если получатель Http Observable находится в том же классе обслуживания, результат равен нулю.Если я разбиваю запрос потребителя на класс компонентов Angular, он работает нормально.Что делает Rx's Observable таким странным?Я думаю, что скоро, когда я subscribe к нему, он будет выполнен.

Есть идеи, что не так с моим кодом?

1 Ответ

0 голосов
/ 20 сентября 2018

Да, это происходит потому, что функция, переданная в subscribe, не вызывается до того, как вы вернете список products.

Рассмотрим более простой пример:

function f() {
    let flag: boolean = false;

    setTimeout(() => flag = true, 10);

    return flag;
}

С setTimeout вы ставите новую задачу в цикл обработки событий JavaScript , как и с http.get.Задачи в цикле событий всегда выполняются после Функция, которая их туда возвращает, возвращает.В моем примере возвращаемое значение всегда будет false, независимо от того, насколько мал время ожидания.

Возвращаясь к вашему примеру, вам нужно вернуть Observable из вашей функции.Вместо того, чтобы пытаться присвоить возвращаемое значение вызова GET локальной переменной products, вы напрямую возвращаете вызов GET.Вот так:

getProducts(): Observable<IProduct[]> {
    // your get call ...
    return productsObservable;
}

Теперь это, вероятно, не решит все за вас, потому что теперь вам нужно иметь дело с Observable в ваших функциях потребителя.Но это более или менее важно для всей модели Observable ... чтобы уведомить конечного потребителя об изменениях данных.

В Angular вы можете работать с Observables , используя асинхронную трубу .

...