使用RxJS 5.0.0-rc.1
,我尝试通过使用Observer
交换数据,以与how generators/iterators work类似的方式与Observable
和yield
进行通信和.next()
。目的是了解对.subscribe
的调用返回的内容,并根据该内容修改/更新我的可观察流中的以下值。
我不完全确定这是否可能。但是,我发现你可以捕获.subscribe
回调引发的异常。以下代码段打印出"Boom!"
:
var source = Observable.create((observer) => {
try {
observer.next(42);
} catch (e) {
// This will catch the Error
// thrown on the subscriber
console.log(e.message);
}
observer.complete();
});
source.subscribe(() => {
throw new Error('Boom!');
});
那么,如果不是投掷,订户返回一个值呢? Observable
有没有办法检索它?也许我正以错误的方式接近这一点。如果是这样,那么"反应性"在这种情况下做事的方式?
非常感谢。
修改
我提出的一种可能方法是在流中的每个项目上提供回调函数。类似的东西:
var source = Observable.create((observer) => {
// This will print "{ success: true }"
observer.next({ value: 42, reply: console.log });
observer.complete();
});
source.subscribe(({ value, reply }) => {
console.log('Got', value);
return reply({ success: true });
});
还有其他想法吗?
编辑2
由于我原来的问题对我想要实现的目标产生了一些困惑,我将描述我的现实世界情景。我正在编写用于通过队列管理消息的模块的API(很像简化的,在内存中,AMQP-RPC机制),虽然RxJS非常合适。
它的工作方式与您期望的一样:Publisher
将消息推送到队列,然后传递给Consumer
。在术语中,Consumer
可以回复Publisher
,如果感兴趣,可以收听该回复。
在理想情况下,API看起来像这样:
Consumer().consume('some.pattern')
.subscribe(function(msg) {
// Do something with `msg`
console.log(msg.foo);
return { ok: true };
});
Publisher().publish('some.pattern', { foo: 42 })
// (optional) `.subscribe()` to get reply from Consumer
该示例将打印42
。
回复Publisher
的逻辑位于Consumer
函数中。但实际响应是来自.subscribe()
回调的。这引出了我的原始问题:我应该如何从流的创建者那里获取返回的值?
将Consumer#consume()
视为:
/**
* Returns an async handler that gets invoked every time
* a new message matching the pattern of this consumer
* arrives.
*/
function waitOnMessage(observer) {
return function(msg) {
observer.next(msg);
// Conceptually, I'd like the returned
// object from `.subscribe()` to be available
// in this scope, somehow.
// That would allow me to go like:
// `sendToQueue(pubQueue, response);`
}
}
return Observable.create((observer) => {
queue.consume(waitOnMessage(observer));
});
它更有意义吗?
答案 0 :(得分:2)
发电机和可观测量之间确实存在相似之处。如您所见here,observables(异步值序列)是iterables的异步版本(值的同步序列)。
现在,生成器是一个返回Iterable
的函数。但是,Rxjs Observable
包含一个生成器 - 也就是生成器(通过调用subscribe
执行/启动)和生成的异步值序列(通过传递Observer
对象观察到的) 。 subscribe
调用返回Disposable
,允许您停止接收值(断开连接)。因此,虽然生成器和可观察对象是双重概念,但使用它们的API会有所不同。
默认情况下,您无法使用rxjs observable API进行双向通信。你可能可以通过在主题中构建自己的反向通道来做到这一点(注意你必须有一个初始值来启动循环)。
var backChannel = Rx.Subject();
backChannel.startWith(initialValue).concatMap(generateValue)
.subscribe(function observer(value){
// Do whatever
// pass a value through the backChannel
backChannel.next(someValue)
})
// generateValue is a function which takes a value from the back channel
// and returns a promise with the next value to be consumed by the observer.
你可以考虑用以下内容包装:
function twoWayObsFactory (yield, initialValue) {
var backChannel = Rx.BehaviorSubject(initialValue);
var next = backChannel.next.bind(backChannel);
return {
subscribe : function (observer) {
var disposable = backChannel.concatMap(yield)
.subscribe(function(x) {
observer(next, x);
});
return {
dispose : function (){disposable.dispose(); backChannel.dispose();}
}
}
}
}
// Note that the observer is now taking an additional parameter in its signature
// for instance
// observer = function (next, yieldedValue) {
// doSomething(yieldedValue);
// next(anotherValue);
// }
// Note also that `next` is synchronous, as such you should avoir sequences
// of back-and-forth communication that is too long. If your `yield` function
// would be synchronous, you might run into stack overflow errors.
// All the same, the `next` function call should be the last line, so order of
// execution in your program is the same independently of the synchronicity of
// the `yield` function
否则,您描述的行为似乎是异步生成器的行为。我从来没有使用过这样的,但是因为这是一个未来版本的javascript的提议,我想你可以 已经开始尝试使用Babel(参见https://github.com/tc39/proposal-async-iteration)。
编辑:
如果您正在寻找一种环回机制(不太通用的方法,但很适合您的用例,如果您想要做的事情很简单),expand
运算符可以提供帮助。要了解其行为,请查看doc以及SO上的以下答案,以获取在具体情况下使用的示例:
基本上expand
允许您向下游发出值并在生产者中同时反馈该值。