Обертывание наблюдаемых методов

Кажется, я не могу обернуть голову вокруг цепочки/обертывания наблюдаемых. Я использую Angular2 rc1 с RxJs в Typescript в Visual Studio 2015.

У меня есть сервисный метод saveProduct в классе ProductService:

public saveProduct(product: Product): Observable<string> {
    let options = new RequestOptions({ headers: new Headers({ 'Content-Type': 'application/json' }) });
    return this.http.post(this.config.apiUrl + '/product', JSON.stringify(product), options).map(this.extractData).catch(this.handleError);
}

Я использую его в компоненте angular2:

public save() {
    this.productService.saveProduct(this.product).subscribe(
        result => this.productSaveExecuted(result),
        error => this.handleError(error)
    );
}

Компонент заключен в модальное диалоговое окно. Если бы я закрыл диалоговое окно после вызова метода сохранения компонента, диалоговое окно было бы закрыто до завершения действия сохранения. Итак, я хочу, чтобы функция сохранения компонента также возвращала Observable, потому что компонент заключен в модальный div, который я хочу закрыть после успешного сохранения. Как мне это сделать?


person Mcanic    schedule 26.05.2016    source источник


Ответы (2)


Что-то вроде этого:

public save(): Rx.Observable<{ success: boolean }> {
    return this.productService
        .saveProduct(this.product)
        .select(result => {
            this.productSaveExecuted(result);
            return { success: true };
        })
        .catch(error => {
             this.handleError(error);
             return Rx.Observable.return({ success: false });
        });
}

Метод save вернет наблюдаемое, которое при подписке попытается сохранить продукт.

Подписка на метод save:

save()
    .subscribe(result => {
        if(result.sucess)
            // everything went well
        else 
            // something went wrong
    })

Я думаю, это то, что вы хотите... вы не совсем ясны в своем вопросе.

person Nypan    schedule 26.05.2016
comment
Спасибо за ваш ответ, я думаю, что ваш ответ именно то, к чему я стремлюсь. Однако VS2015 выдает ошибку: свойство select не существует для типа Observable‹Product[]›». Кажется, Angular2 использует только подмножество rxjs? Я вижу select.js в каталоге node_modules\rx\src\core\linq\observable\ Как мне импортировать это в мой класс Angular2? - person Mcanic; 27.05.2016
comment
Хорошо, я не очень хорошо разбираюсь в Angular2, но если Observable, возвращаемый saveProduct, является Rx.Observable, на нем должен присутствовать выбор. Попробуйте изменить тип вывода на Rx.Observable, если это не сработает, вам может потребоваться включить в свое решение больше Rxjs (rx.all.js и rx.all.d.ts включают все). Взгляните на github.com/Reactive-Extensions/RxJS для получения дополнительной информации о rxjs в целом. . - person Nypan; 27.05.2016
comment
Что ж, поразмыслив над Observables, не так-то просто обернуть observable в другой Observable, таким образом передав его родительскому объекту. Оператор select, который вы придумали, не существует в RxJS, включенном в Angular 2 rc1. Вы можете связать Observable с помощью оператора Observable.flatmap и вернуть результирующий Observable, но вы также можете просто вернуть обещание 'then' из метода toPromise Observable. Вернемся к этому в ближайшее время. - person Mcanic; 01.06.2016
comment
Хорошо, select — это то же самое, что и map, а flatMap — это то же самое, что и selectMany, они просто псевдонимы друг для друга. Итак, если select не существует, попробуйте map. И если это не сработает, вы можете импортировать нужные вам операторы, взгляните на stackoverflow.com/questions/34113750/, не уверен, насколько это актуально, но если вы посмотрите в нем кто-то решит, как получить доступ к операторам rxjs в angular. Это неотъемлемая часть реактивного программирования. - person Nypan; 01.06.2016

Наблюдаемые могут быть «обернуты» в другой наблюдаемый объект следующим образом:

public save(): Observable<{}> {
    console.log("productdetails.component save was called");

    return Observable.create(observer => {
        this.productService.saveProduct(this.product).subscribe(
            result => this.productSaveExecuted(result),
            error => this.handleError(error)
        );
        observer.next(),
        function (err) {
            console.log('Error: ' + err);
        },
        //call complete if you want to close this stream (like a promise)
        observer.complete();
    });

}

Другим решением было бы подписаться на полученный Observable из productService и вернуть обещание из метода .toPromise().

Спасибо Nypan за поддержку моего учебного процесса :)

person Mcanic    schedule 03.06.2016