Promise Chaining / Cascading to RxJS angular 1 to angular 2

Posted

技术标签:

【中文标题】Promise Chaining / Cascading to RxJS angular 1 to angular 2【英文标题】: 【发布时间】:2016-11-30 01:59:49 【问题描述】:

我目前正在尝试将一些好的旧 $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 他们。 很好,感谢您的澄清 【参考方案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() 最后只能执行一次。

以上是关于Promise Chaining / Cascading to RxJS angular 1 to angular 2的主要内容,如果未能解决你的问题,请参考以下文章

jQuery - Chaining

jQuery Chaining

jQuery - Chaining

jQuery - Chaining 链接技术

jQuery - 链(Chaining):把动作/方法链接在一起

jQuery - 链(Chaining)