ReactiveX / rxjs

A reactive programming library for JavaScript
https://rxjs.dev
Apache License 2.0
30.7k stars 3k forks source link

Implement Observable.spawn(function* (){}) #1497

Closed sladiri closed 7 years ago

sladiri commented 8 years ago

It seems that the spawn function is not implemented in RxJS5. As such, I cannot yield to Observables. Our use case is to retrieve paginated data from a web-server. This is my how I can do it in RxJS4:

Rx.Observable.spawn(function* () {
  const limit = 2;
  try {
    const aprxjs = Rx.Observable.fromCallback(api);
    const lazyArr = [];
    yield aprxjs(0)
      .expand(v => v < limit ? aprxjs(v) : Rx.Observable.empty())
      .do(v => lazyArr.push(v));
  }
  catch (e) { console.log('er', e.stack); }
}).subscribe();
benlesh commented 8 years ago

Thanks for pointing this out, @sladiri. We'll discuss adding this functionality, in the meantime you should be able to do this with:

Observable.from((function* () {
  yield Observable.of('foo');
}())
.mergeAll() // choose your merge strategy here.
.subscribe();
benlesh commented 8 years ago

To be clearer, @sladiri, I'm not suggesting what I've put above is a replacement for spawn. Rather, it will work for your use-case. spawn is doing other things to send values retrieved from async types back into the generator as a co-routine.

I suppose the discussion here is about whether or not this belongs in this library, or if this is an interesting one-off function for supporting various async types using a generator. Just to clarify.

@staltz? @mattpodwysocki? @trxcllnt? what are your thoughts?

staltz commented 8 years ago

Given

var spawned = Rx.Observable.spawn(function* () {
  var v = yield thunk(12);
  var w = yield [24];
  var x = yield Rx.Observable.just(42);
  var y = yield Rx.Observable.just(56);
  var z = yield Promise.resolve(78);
  return v + w[0] + x + y + z;
});

I'd prefer to convert each of these pieces into an Observable and compose them as Observables. So I can't see much of a use for spawn if we have from(Iterator).

sladiri commented 8 years ago

Thank you for the explanation. I am new to this library and I overlooked the possibility of using from().

geyang commented 8 years ago

took me a while to figure out that spawn is not implemented in 5.0. Thanks for creating this issue!

I'm looking at this because I'm writing a reactive saga for a reactive redux library called luna.

alex-okrushko commented 8 years ago

Lost a couple of hours trying to understand why "Property 'spawn' does not exist on type 'typeof Observable'." It appears that the documentation is for RxJS4 exclusively and the MIGRATION doc doesn't not mention that spawn, or for that matter generate are not implemented. Is there a documentation for RxJS5 somewhere? I'm new to this framework, so I refer the documentation a lot.

benlesh commented 8 years ago

Is there a documentation for RxJS5 somewhere?

@alex-okrushko: It's a work in progress, but most of it can be found via the README on this repo, and here: http://reactivex.io/rxjs/

benlesh commented 8 years ago

@jhusain this is very similar to what we were working on today at Netflix. We should definitely look at porting spawn into Rx 5.

alex-okrushko commented 8 years ago

@blesh Wow, that documentation is really good (very easy to consume)! Thanks a lot!

benlesh commented 7 years ago

Closing as inactive.

pabl-o-ce commented 6 years ago

hi @benlesh, in typescript the types of from is:

export declare class FromObservable<T> extends Observable<T> {
    private ish;
    private scheduler;
    constructor(ish: ObservableInput<T>, scheduler?: IScheduler);
    static create<T>(ish: ObservableInput<T>, scheduler?: IScheduler): Observable<T>;
    static create<T, R>(ish: ArrayLike<T>, scheduler?: IScheduler): Observable<R>;
    protected _subscribe(subscriber: Subscriber<T>): any;
}

so it can't create from a generator function without a type error...

maybe I'm wrong but just want to know how handle like async/await with observables. I made some observables functions that the flow depends in sequence like async / await does with promises... if you can point me to a good direction... love to hear from you ๐Ÿ™ƒ

benlesh commented 6 years ago

@pablocarreraest be sure you're calling your generator function: from(function* () { ... }()) (Notice the last () in there)

pabl-o-ce commented 6 years ago

@benlesh I try:

public findByIdOrName$ (id: string): Observable<Movie> {
 return Observable.from(function* (): IterableIterator<Movie> {
    try {
        const movie = yield this.findById$(id);
        return (movie) ? movie : yield this.findByName$(id);
    } catch (error) {
        return Observable.throw(error);
      }
   }());
}

I get a error of:

file: 'file.ts'
severity: 'Error'
message: 'Argument of type 'IterableIterator<Movie>' is not assignable to parameter of type 'ArrayLike<{}>'.
Property 'length' is missing in type 'IterableIterator<Movie>'.'
source: 'ts'

or maybe as you say I work with async / await and handle observables with toPromise()๐Ÿค”

benlesh commented 6 years ago

Hmm... sounds like a typings issue. This will definitely work in normal JavaScript. Try casting as Iterable<Movie>, and if all else fails, I guess any, and we'll file a separate bug

pabl-o-ce commented 6 years ago

with Iterable<Movie>

file: 'file.ts'
severity: 'Error'
message: 'Argument of type 'Iterable<Movie>' is not assignable to parameter of type 'ArrayLike<{}>'.
  Property 'length' is missing in type 'Iterable<Movie>'.'
source: 'ts'
code: '2345'

and with any

๐Ÿ‘

but when I use the function with any at the first yield won't get me nothing of return in other words:

public findByIdOrName$ (id: string): Observable<Movie> {
    return Observable.from(function* (): any {
      try {
        console.log(id); // get the id or name -> beauty and the beast
        const movie = yield this.findById$(id); // function that return a observable, in here die just nothing happens
        console.log(movie); // --> nothing it don't get to this 
        return (movie) ? movie : yield this.findByName$(id); // function that return a observable
      } catch (error) {
        return Observable.throw(error);
      }
    }());
}

at console:

> beauty and the beast

I'm like ๐Ÿง>๐Ÿค”>๐Ÿคฏ>๐Ÿคจ so I can't get to ๐Ÿ˜Ž environment (sorry about the faces is friday)

lock[bot] commented 6 years ago

This thread has been automatically locked since there has not been any recent activity after it was closed. Please open a new issue for related bugs.