【问题标题】:Promise Chaining / Cascading to RxJS angular 1 to angular 2Promise Chaining / Cascading to RxJS angular 1 to angular 2
【发布时间】:2023-03-17 06:28:01
【问题描述】:

我目前正在尝试将一些好的旧 $http Promises 转换为 angular2 中的 rxJs observables。

一个非常简单的例子,我过去经常在 Angular 1 中做的事情:

// Some Factory in Angular 1
var somethings = [];
var service = {
    all: all
};
return service;

function all() {
    return $http
        .get('api/somethings')
        .then(function(response) {
            somethings = parseSomethings(response.data);
            return somethings;
        });
}

// Some Controller in Angular 1
var vm = this;
vm.somethings = [];
vm.loading = true;

loadThings();

function loadThings() {
    SomeFactory
        .all()
        .then(function(somethings) {
            vm.somethings = somethings;
        })
        .finally(function() {
            vm.loading = false;
        })
}

现在我可以使用 RxJs Observable 和 Subject 实现与 angular2 类似的功能。但我不确定如何将“完成挂钩”返回给调用者。 (例如:angular1 控制器中的加载)

我对 angular2 的尝试是类似的:

// Some Service in Angular 2
export class SomeService {
    private _somethings$: Subject<Something[]>;
    private dataStore: {
        somethings: Something[]
    };

    constructor(private http: Http) {}

    get _somethings$() : Observable<Something[]> {
        return this._somethings$.asObservable();
    }

    loadAll() {
        this.http
            .get(`api/somethings`)
            .map(response => response.json())
            .subscribe(
                response => {
                    this.dataStore.somethings = parseSomethings(response.data);
                    this._somethings$.next(this.dataStore.somethings);
                }
            );
    }
}

//Some Component in Angular 2
export class SomeComponent() {

    constructor(private someService: SomeService) {}

    ngOnInit() {
        this.someService.loadAll();
        this.somethings = this.someService.somethings$;
    }
}

注意

我在这里使用了 Subject / Observable,这样当我创建/更新/删除“某物”时,我可以调用 .next 来通知订阅者。

例如:

create(something: Something) : Observable<Something>{
    return this.http.post(`api/somethings`, JSON.stringify(something))
        .map(response => response.json())
        .do(
            something => {
                this.dataStore.somethings.push(something);
                this._somethings$.next(this.dataStore.somethings); //Notify the subscribers
            }
        );
}

注意

这里我在方法中使用了 .do,当在“表单组件”中调用该方法时,我订阅只是为了获取完成处理程序:

this.someService.create(something).subscribe(
(ok) => ...
(error) => ...
() => stop loading indicator
)

问题

  • 我们如何在 Angular 2 中使用 RxJs 将完成挂钩传递给调用者(例如 angular 1 控制器
  • 存在哪些替代路径来实现类似行为?

【问题讨论】:

  • 嘿,我对 AngularJS 不太熟悉。但据我了解,您想知道get 函数何时完成以将loading 设置为false?在这种情况下,请将您的服务中的 subscribe 块移动到您的组件并在那里设置 loading 标志。
  • 好的,我是否应该在组件中取消订阅(可以在单击按钮调用 create.subscribe() 之后说)
  • 不,http.gethttp.post 将在返回响应后完成,因此您无需 unsubscribe 他们。
  • 很好,感谢您的澄清

标签: angularjs angular promise rxjs observable


【解决方案1】:

您的最后一个代码示例很好。只需使用map() 而不是subscribe() 并在呼叫站点订阅。

你可以使用

return http.post(...).toPromise(val => ...))

return http.post(...).map(...).toPromise(val => ...))

获得与 Angular 中相同的行为,您可以使用 .then(...) 链接后续调用

【讨论】:

  • 我在考虑使用地图 aswel。 .do 适合这个 aswel 吗?
  • map()返回的值转发给订阅者。如果您不想修改该值而只是对每个事件造成一些副作用,那么do() 也可以。
  • 我可以假设多个 .map 调用只会像 .then 那样 cascade 吗?
  • 没错。您可以级联各种运算符,也可以多次级联。仅subscribe() 最后只能执行一次。
猜你喜欢
  • 2017-08-03
  • 2018-09-22
  • 1970-01-01
  • 1970-01-01
  • 2017-02-02
  • 1970-01-01
  • 2019-05-31
  • 1970-01-01
  • 2017-08-14
相关资源
最近更新 更多