RxJS:等待一个值,然后释放观察者

RxJS:等待一个值,然后释放观察者,rxjs,Rxjs,我真的不知道如何问这个问题,但我的应用程序中有类似的代码,我想知道是否有更好的方法来处理它 const d=this.$q.defer(); const s=此。更改$//{ d、 解决(本承诺书的目的); s、 取消订阅(); }); 回报承诺; 我尝试过使用takeLast之类的东西,但我不希望流完成,因为它对用户输入(例如搜索字段)做出反应。据我所知,.toPromise()仅在流完成时解析 有没有可能简化我的代码,避免一直订阅和取消订阅?更重要的是,我的代码是不是糟糕的做法?在您的情况

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

const d=this.$q.defer();
const s=此。更改$//{
d、 解决(本承诺书的目的);
s、 取消订阅();
});
回报承诺;
我尝试过使用
takeLast
之类的东西,但我不希望流完成,因为它对用户输入(例如搜索字段)做出反应。据我所知,
.toPromise()
仅在流完成时解析


有没有可能简化我的代码,避免一直订阅和取消订阅?更重要的是,我的代码是不是糟糕的做法?

在您的情况下,您希望在开始聆听第一个值时完成:

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秒后自动被拒绝。

为了使用从可观察到的数据派生的一系列承诺,我将假设您的逻辑如下:

// 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
的承诺,然后订阅可观察到的,在每次发射时,解决或拒绝该承诺,然后创建一个新的承诺,当消费者处理完之前的承诺后,可以通过
getNewPromise
获得

这种逻辑并不完美,因为如果可观察对象的发射速度超过
handleValue
的处理速度,它将跳过一些承诺。要解决这个问题,需要某种程度上排队承诺。但你明白了

但实际上,您在这里所完成的只是将一个非常好的可观察对象转换为一系列通过反复调用
getNewPromise
返回的承诺。但是一个可观察的东西已经是一系列的东西了,
subscribe
允许你一次得到一个。因此,上面的整个代码几乎完全等同于

this.changes$.subscribe(handleValue)
还有一个额外的优点是错误和完成是自动处理的

在您的方法中,您混合了两种不同的范例——可观察和承诺——这很可能会让您和任何阅读您的代码的人感到困惑。但它们被设计用来做不同的事情:承诺代表一次性的未来价值,而可观察的代表未来价值流。你似乎试图用承诺来代表可观察到的个体排放。但是一个可观测的物体上的辐射已经由可观测物体本身来表示了
toPromise
设计用于在由于可观测对象仅发出单个值或可能立即发出错误而有意义的情况下弥合这一差距


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

谁在消费
d
,如何消费?如果我理解得很好,您可以尝试使用
first
操作符获取
change$
的第一项,
flatMap
将其转换为
d
并订阅它是一种不好的做法。Try:
返回此.changes$.take(1).mapTo(this.promisewerwaitingfor).toPromise()
@torazaburo多个方法是-此特定代码示例用于确保在使用多个其他方法继续之前,数据已准备就绪。特别是在这种情况下,
this.promiseweewaitingfor
必须在用户按下enter键后解析,然后再继续,但它也会返回到一个外部组件,该组件使用解析后的数据作为搜索建议列表。问题中提到,我不想在需要对流做出反应时完成流。如果我这样做了,我就必须一直创建一个新的流。使用
take(1)
将立即返回,因为在使用vanilla时,当运行此代码时,流中几乎总是有数据,然后
take(1)
将等待下一个值。若你们不想完成,那个么你们不应该使用承诺,而应该根据你们的流的排放量来做一些事情。