RxJS:等待一个值,然后处置观察者

时间:2017-07-11 06:16:28

标签: rxjs

我不确定如何提出这个问题,但我的应用程序中的代码与此类似,我想知道是否有更好的方法来处理它。

const d = this.$q.defer();
const s = this.change$  // <- A regular Subject, that emits whenever changes to the model arrive
    .subscribe(() => {
        d.resolve(this.promiseWereWaitingFor);
        s.unsubscribe();
    });

return d.promise;

我已尝试使用takeLast这类内容,但我不想让流完成,因为它会对用户输入作出反应(例如搜索字段) )。根据我的理解,.toPromise()仅在流完成时解析。

是否可以简化我的代码,以避免一直订阅和取消订阅?更重要的是,我的代码甚至是不好的做法?

2 个答案:

答案 0 :(得分:0)

在你的情况下,你希望在开始收听第一个值后到达时完成:

this.change$.take(1)
  .mapTo(this.promiseWereWaitingFor)
  .toPr‌​omise();

当一个值到达时,这将履行您的承诺。根据您的要求,这可能是一个问题;承诺在该值到达之前不会解决。为了保护这一点,您可以添加超时:

this.change$.take(1)
  .mapTo(this.promiseWereWaitingFor)
  .timeout(2 * 1000) /* 2 seconds for promise to fulfil */
  .toPr‌​omise();

这样,如果没有传播任何值,则承诺会在2秒后自动被拒绝。

答案 1 :(得分:0)

为了消耗一系列来自observable的promise,我假设你的逻辑类似于以下内容:

// Handle a series of promises.
function handleSeries() {
  return getNewPromise().then(handleValue).then(handleSeries);
}

其中(使用本机承诺),getNewPromise实现如下:

let promise, resolveFunc, rejectFunc;

function getNewPromise() { return promise; }

function makeNewPromise() {
   promise = new Promise((resolve, reject) => {
     resolveFunc = resolve;
     rejectFunc = reject;
   });
}

makeNewPromise();

this.changes$.subscribe(
  change => { resolveFunc(change); makeNewPromise(); },
  error => { rejectFunc(error); makeNewPromise(); }
);

换句话说,我们定义一个名为promise的承诺,然后订阅observable,并在每次发射时,解析或拒绝该承诺,然后创建一个消费者可以用{{1}获得的新承诺当他完成处理先前的承诺时。

这个逻辑并不完美,因为如果observable发出的速度超过getNewPromise可以处理它们,它将跳过一些承诺。要解决这个问题,需要以某种方式排队承诺。但是你明白了。

但是你在这里完成的所有事情,实际上是将一个非常好的可观察变为一系列通过重复调用handleValue而返回的承诺。但是一个可观察的东西已经是一系列事物,getNewPromise允许你一次得到一个。因此,上面的整个代码几乎完全等同于只说

subscribe

具有额外的优势,即自动处理错误和完成。

通过您的方法,您将混合两种不同的范例 - 可观察和承诺 - 这种方式可能会让您和阅读代码的任何人感到困惑。但它们旨在做不同的事情:承诺代表一次性的未来价值,而观察代表未来价值的流。您似乎试图使用承诺来代表可观察的个别排放。但是可观测量的排放已经由可观察物本身代表。 this.changes$.subscribe(handleValue) 旨在弥合这一差距,因为它是有意义的,因为observable只会发出一个值,或者可能立即发出错误。

因此,如果我理解你的情况,你应该跳过使用承诺,让你的消费者按照预期使用observable,直接订阅它。