Murhaf Sousli
Murhaf Sousli

Reputation: 13296

rxjs pass parameter in Subject.next

I'm new to rxjs, I'm trying to pass parameter in Subject.next(args) I have the following class:

@Injectable()
export class ListPosts {
baseURL: string = 'http://localhost/wptest/api';
_load = new Subject();

constructor(private http: Http) {
    var currentPage = this._load
        .scan((currentPage) => currentPage + 1, 0)

    var postResponses = currentPage           //args here is undefined
        .flatMap(args => this.fetchPosts(args))
        .share();

    var loadedPosts = postResponses
        .map(json => json.posts)
        .scan((allPosts, newPosts) => allPosts.concat(newPosts), []);

    this.loadedPostCount = loadedPosts.map(p => p.length);
    this.totalPostCount = postResponses.map(json => json.count_total);

    this.completed = Observable.combineLatest(this.loadedPostCount, this.totalPostCount, (loaded, total) => loaded >= total);

    this.posts = loadedPosts;
}

fetchPosts(args: any) {
    console.log("count: " + args[0] + " page :" + args[1] + " type: "+ args[2]);
}

loadMore(args: any) {
    this._load.next(args);
}
}

but if I change currentPage to this._load, it works

var postResponses = this._load
        .flatMap(args => this.fetchPosts(args)) //args here is defined
        .share();

I need to get the args through currentPage, how can I fix it?

Upvotes: 1

Views: 4355

Answers (1)

Lodewijk Bogaards
Lodewijk Bogaards

Reputation: 19987

There are a couple of points after looking at your code.

In _load = new Subject(); the type parameter (or generic type if you will) is left out, so _load actually is of the default type Subject<any> (a.k.a. Subject<{}>). It seems to me from looking at fetchPosts that you expect it to be of the type any[] or perhaps even [number, string, string].

Would you have written _load = new Subject<any[]>(); and fetchPosts(args: any[]) typescript would have produced a type error, because the line: .scan((currentPage) => currentPage + 1, 0) transforms the type parameter from type any to type number. This scan operation does nothing with the input, but simply increase a number currentPage starting at 0 for every type the Subject receives an input. If you then feed this number as args to fetchPosts and try to log args[0], args[1] and args[2] you will get undefined, since a number is not an array. If you will log args itself you will find that you will see the currentPage number.

Here is something that might work for you or could give you an idea how your solution could work:

  type Args = [number, string, string];
  const _load = new Rx.Subject<Args>();
  const _loadCount = _load.scan(count => count + 1, 0);
  const _loadWithCount = Rx.Observable.zip(_load, _loadCount,
    (args, count) : Args => [count, args[1], args[2]]
  );

Upvotes: 2

Related Questions