【问题标题】:How can I use Observables instead of Promises?如何使用 Observables 而不是 Promise?
【发布时间】:2018-01-10 00:24:39
【问题描述】:

我有一个带有一些方法的服务,它们中的大多数都需要完成某个回调才能完成它的工作。使用 Promises,在伪中,很容易做到这一点:

ready = http.get(stuff); // Returns a promise, resolves after a while

methodOne() { // methods sometimes called before promise resolves
    this.ready.then(_ => { 
        // doStuff
    });
}

methodTwo() {
    return this.ready.then(d => {
        // doOtherStuff
    });
}

基本上我需要做这些事情,只有当我确定服务已经准备好时。 我实际上只需要检查它是否准备好了(methodOne 在做什么,只是用methodTwo 说明,它也很容易做更多的东西)。

我想全力以赴地使用 Observables,但对于这种特殊情况,我发现很难与 Observables 的类似解决方案竞争。

Promises 会记住该值并知道它是否已解决。一个 Observable 稍微复杂一些,创建同样的流程似乎很麻烦。我需要订阅 Observable 的任何内容,以便知道它何时准备就绪。有时该方法被提前调用 - 在 Observable 发射之前,有时在 Observable 已经发射之后调用。

我现在有这个,但它似乎不起作用:

this.ready$ = someObservable // Will fire after a litle while but never finish - i only need the first to check though.
  .publishReplay(1).refCount(); // Trying to replay if subscription comes after emit.

this.ready$.subscribe(_ => {
    // This will be called
});

methodOne() { 
    this.ready$.subscribe(_ => {
        // Not called
    });
};

也许我误解了publishReplayrefCount 的用法?

【问题讨论】:

  • “由于我在做一个 Angular 项目,首选的方式是全力以赴的 Observables” 首选谁?有什么依据?还有哪些支持数据?
  • @T.J.Crowder 我将编辑我的陈述,因为它可能是主观的,但我已经看到它提到了几个地方。 stackoverflow.com/questions/37364973/…
  • 我很快就投票赞成关闭 - 我需要一个带有 Observables 的解决方案,措辞可以(并且已经)改变,因此不再基于意见。
  • “Ore Observables 真的是 Promises 的一个很好的替代品吗”,从表面上看,是在征求意见。 (顺便说一句,这不是我的近距离投票。) 如果问题真的是“我如何使用 Observables 而不是 Promises?”我会编辑问题标题来说明这一点。我还会进行编辑以使其更加简洁。 (并且在 SO 答案中表达意见的人不具备支持数据的合理理由。)
  • @T.J.Crowder 好点,标题已更改。

标签: javascript angular promise es6-promise reactivex


【解决方案1】:

我认为您正在寻找的是AsyncSubject。它很好地模仿了 promise 的行为。这是描述:

AsyncSubject 是一个变体,其中只有最后一个值 可观察的执行被发送给它的观察者,并且只有当 执行完成。

在您的情况下如何使用它:

subject = new AsyncSubject();
ready = streamOfData(stuff).first().subscribe(subject);    
methodOne() {
    return this.subject.asObservable();
}

主题订阅 first 操作符返回的底层 observable 并等待它完成。它收集所有订阅者,但不向他们发送任何值。一旦底层的 observable 完成,它就会记住该值并将其发送给收集的订阅者。所有新的未来订阅者都将立即传递这个存储的解析值。

这是一个简单的例子,展示了你可以在 observable 完成之前或之后订阅:

const subject = new AsyncSubject();
const o = subject.asObservable();
o.subscribe((v) => {
  console.log(v);
});
interval(500).first().subscribe(subject);

setTimeout(() => {
  o.subscribe((v) => {
    console.log(v);
  });
}, 2000);

【讨论】:

  • 我应该提到这个例子没有加载一个http请求——它确实是一个永无止境的流。我会更新我的问题以更清楚地反映这一点。我想我可以在我的 observable 上使用 .first() ......我会试试看。
  • @PerHornshøj-Schierbeck,那么你应该如何对永不结束的流使用 Promise? Promises 是关于一个已解决的值。
  • 我会包装第一个发射并解决承诺然后
  • @PerHornshøj-Schierbeck,好吧,那就用first()吧。更新了我的答案
  • 这表现得非常像我自己对 replaySubject(1).refCount() 的尝试。它适用于 Promise(刚刚测试),但两个 Observable 示例仅在第一次/唯一发出之前调用订阅(您的 methodOne)时才有效。想想看,调用 .first() 取消订阅,也许这就是为什么?
猜你喜欢
  • 1970-01-01
  • 2019-08-17
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-01-07
  • 2023-03-27
  • 1970-01-01
相关资源
最近更新 更多