简体   繁体   English

可观察的 rxJs 回调是异步的

[英]rxJs callback with observable being asynchronous

I have a map operation in my rxjs flow我的 rxjs 流程中有一个地图操作

streaming.map((data) => {
  //example async call
  methodCall.then((response) => {
    return data.test
  })
})
.filter((value) => ...);

The thing is filter is called before data.test is returned naturally.事情是在 data.test 自然返回之前调用过滤器。 So I tried converting it to switchMap and returning an observable所以我尝试将其转换为 switchMap 并返回一个 observable

streaming.switchMap((data) => {
  return Observable.create((observer) => {
    //example async call
    methodCall.then((response) => {
      observer.next(data.test);
      observer.complete();
    });
  });
})
.filter((value) => ......);

I assumed that IN THIS case since we are returning an observable with explicit timing on next is called the filter would be called ONLY after the observer.complete is called but filter was called prematurely with the value variable undefined.我假设在这种情况下,因为我们在 next 上返回一个具有明确计时的可观察对象,所以过滤器只会在调用观察者.完成之后被调用,但过滤器被过早地调用,值变量未定义。

How would I accomplish this normally using rxJs我通常如何使用 rxJs 完成此操作

I think you're missing a return statement or something.我认为您缺少 return 语句或其他内容。 That's why it gives you unexpected results.这就是为什么它会给你意想不到的结果。 The switchMap() operator subscribes to the Observable returned from its callback and reemits all its items until another Observable is returned. switchMap()运算符订阅从其回调返回的 Observable 并重新发送其所有项目,直到返回另一个 Observable。 It doesn't wait for complete notification.它不会等待完整的通知。

This should simulate your example:这应该模拟你的例子:

function methodCall() {
  return new Promise(resolve => setTimeout(() => {
    resolve(123);
  }, 1000));
}

Observable.of(42)
  .do(value => console.log('start: ' + value))
  .switchMap((data) => {
    return Observable.create((observer) => {
      //example async call
      methodCall().then((response) => {
        observer.next(response);
        observer.complete();
      });
    });
  })
  .filter(value => true)
  .subscribe(value => console.log('next: ' + value));

See live demo: https://jsbin.com/focili/2/edit?js,console看现场演示: https : //jsbin.com/focili/2/edit?js,console

Notice that 123 is emitted when the Promise resolves.请注意,当 Promise 解析时会发出123

By the way, maybe you don't need to use switchMap() at all.顺便说一句,也许您根本不需要使用switchMap() RxJS 5 treats Observables, Promises, arrays, array-like objects, etc. the same way. RxJS 5 以同样的方式处理 Observables、Promises、数组、类数组对象等。 This means you can interchange Observables for any of the mentioned above.这意味着您可以为上述任何一个交换 Observable。 For example you can use just concatMap() and the result is going to be the same:例如,您可以只使用concatMap()并且结果将是相同的:

function methodCall() {
  return new Promise(resolve => setTimeout(() => {
    resolve(123);
  }, 1000));
}

Observable.of(42)
  .do(value => console.log('start: ' + value))
  .concatMap(value => methodCall())
  .filter(value => true)
  .subscribe(value => console.log('next: ' + value));

See live demo: https://jsbin.com/wipofiv/2/edit?js,console看现场演示: https : //jsbin.com/wipofiv/2/edit?js,console

Notice that concatMap() receives a Promise but it still works as expected a you don't even need to transform it into an Observable.请注意, concatMap()收到一个 Promise 但它仍然按预期工作,您甚至不需要将其转换为 Observable。

Normally you can transform Promise to Observable with fromPromise通常你可以使用fromPromisePromise转换为Observable

streaming.switchMap((data) => Observable.fromPromise(methodCall))
         .filter((value) => ...);

This does all ugly job and you just enjoy RxJS programming.这做了所有丑陋的工作,你只是喜欢 RxJS 编程。

Probably before filter you would need to apply some .map to return data.test instead of data可能在filter之前,您需要应用一些.map来返回data.test而不是data

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM