RXJS 控制可观察调用
RXJS control observable invocation
我在 Angular 2 项目中使用 RxJs version 5。
我想创建一些可观察对象,但我不希望立即调用这些可观察对象。
在version 4 you could control the invocation with (for example) the Controlled command or Pausable Buffers。
但是该功能在版本 5 中不可用 (yet)。
如何在 RxJs 5 中获得这种功能?
我的最终目标是将创建的可观察对象排队并一个一个地调用它们。只有当前一个处理成功时才会调用下一个。
当一个失败时,队列被清空。
编辑
根据@Niklas Fasching 的评论,我可以使用 Publish 操作创建一个可行的解决方案。
// Queue to queue operations
const queue = [];
// Just a function to create Observers
function createObserver(id): Observer {
return {
next: function (x) {
console.log('Next: ' + id + x);
},
error: function (err) {
console.log('Error: ' + err);
},
complete: function () {
console.log('Completed');
}
};
};
// Creates an async operation and add it to the queue
function createOperation(name: string): Observable {
console.log('add ' + name);
// Create an async operation
var observable = Rx.Observable.create(observer => {
// Some async operation
setTimeout(() =>
observer.next(' Done'),
500);
});
// Hold the operation
var published = observable.publish();
// Add Global subscribe
published.subscribe(createObserver('Global'));
// Add it to the queue
queue.push(published);
// Return the published so the caller could add a subscribe
return published;
};
// Create 4 operations on hold
createOperation('SourceA').subscribe(createObserver('SourceA'));
createOperation('SourceB').subscribe(createObserver('SourceB'));
createOperation('SourceC').subscribe(createObserver('SourceC'));
createOperation('SourceD').subscribe(createObserver('SourceD'));
// Dequeue and run the first
queue.shift().connect();
使用 Rx4 的 controlled
当您订阅时 Observable 仍然被调用
RxJS 4 中的 controlled
运算符实际上只是控制 Observable 在 运算符之后的流程。到那时,它全部通过并缓冲该操作员。考虑一下:
(RxJS 4) http://jsbin.com/yaqabe/1/edit?html,js,console
const source = Rx.Observable.range(0, 5).do(x => console.log('do' + x)).controlled();
source.subscribe(x => console.log(x));
setTimeout(() => {
console.log('requesting');
source.request(2);
}, 1000);
您会注意到 Observable.range(0, 5)
中的所有五个值都由 do
立即发出 ... 然后一秒(1000 毫秒)暂停在你得到你的两个值之前。
所以,这真的是背压控制的错觉。最后,该运算符中有一个无界缓冲区。一个数组,它正在收集 Observable "above" 发送的所有内容并等待您通过调用 request(n)
.
将其出列
RxJS 5.0.0-beta.2 复制 controlled
在回答这个问题时,controlled
运算符在 RxJS 5 中不存在。这是出于以下几个原因:1. 没有请求,以及 2. 它的名称显然令人困惑(因此Whosebug 上的这个问题)
如何复制 RxJS 5 中的行为(目前):http://jsbin.com/metuyab/1/edit?html,js,console
// A subject we'll use to zip with the source
const controller = new Rx.Subject();
// A request function to next values into the subject
function request(count) {
for (let i = 0; i < count; i++) {
controller.next(count);
}
}
// We'll zip our source with the subject, we don't care about what
// comes out of the Subject, so we'll drop that.
const source = Rx.Observable.range(0, 5).zip(controller, (x, _) => x);
// Same effect as above Rx 4 example
source.subscribe(x => console.log(x));
// Same effect as above Rx 4 example
request(3);
背压控制
目前 "real backpressure control",一个解决方案是 promise 的迭代器。尽管 IoP 并非没有问题,一方面,每个回合都有一个对象分配。每个值都有一个与之关联的 Promise。另一方面,取消不存在,因为它是承诺。
一个更好的、基于 Rx 的方法是让一个 Subject "feeds" 位于你的可观察链的顶部,而你在其余部分进行组合。
像这样:http://jsbin.com/qeqaxo/2/edit?js,console
// start with 5 values
const controller = new Rx.BehaviorSubject(5);
// some observable source, in this case, an interval.
const source = Rx.Observable.interval(100)
const controlled = controller.flatMap(
// map your count into a set of values
(count) => source.take(count),
// additional mapping for metadata about when the block is done
(count, value, _, index) => {
return { value: value, done: count - index === 1 };
})
// when the block is done, request 5 more.
.do(({done}) => done && controller.next(5))
// we only care about the value for output
.map(({value}) => value);
// start our subscription
controlled.subscribe(x => {
console.log(x)
});
...我们也有一些计划在不久的将来实现具有真正背压控制的可流动可观察类型。对于这种情况,那会更令人兴奋和更好。
您可以通过 publishing the observable. The published observable will only be started after calling connect 将可观察对象的开始与订阅分开。
请注意,所有订阅者将共享对可观察序列的单一订阅。
var published = Observable.of(42).publish();
// subscription does not start the observable sequence
published.subscribe(value => console.log('received: ', value));
// connect starts the sequence; subscribers will now receive values
published.connect();
我在 Angular 2 项目中使用 RxJs version 5。 我想创建一些可观察对象,但我不希望立即调用这些可观察对象。
在version 4 you could control the invocation with (for example) the Controlled command or Pausable Buffers。 但是该功能在版本 5 中不可用 (yet)。
如何在 RxJs 5 中获得这种功能?
我的最终目标是将创建的可观察对象排队并一个一个地调用它们。只有当前一个处理成功时才会调用下一个。 当一个失败时,队列被清空。
编辑
根据@Niklas Fasching 的评论,我可以使用 Publish 操作创建一个可行的解决方案。
// Queue to queue operations
const queue = [];
// Just a function to create Observers
function createObserver(id): Observer {
return {
next: function (x) {
console.log('Next: ' + id + x);
},
error: function (err) {
console.log('Error: ' + err);
},
complete: function () {
console.log('Completed');
}
};
};
// Creates an async operation and add it to the queue
function createOperation(name: string): Observable {
console.log('add ' + name);
// Create an async operation
var observable = Rx.Observable.create(observer => {
// Some async operation
setTimeout(() =>
observer.next(' Done'),
500);
});
// Hold the operation
var published = observable.publish();
// Add Global subscribe
published.subscribe(createObserver('Global'));
// Add it to the queue
queue.push(published);
// Return the published so the caller could add a subscribe
return published;
};
// Create 4 operations on hold
createOperation('SourceA').subscribe(createObserver('SourceA'));
createOperation('SourceB').subscribe(createObserver('SourceB'));
createOperation('SourceC').subscribe(createObserver('SourceC'));
createOperation('SourceD').subscribe(createObserver('SourceD'));
// Dequeue and run the first
queue.shift().connect();
使用 Rx4 的 controlled
当您订阅时 Observable 仍然被调用
RxJS 4 中的 controlled
运算符实际上只是控制 Observable 在 运算符之后的流程。到那时,它全部通过并缓冲该操作员。考虑一下:
(RxJS 4) http://jsbin.com/yaqabe/1/edit?html,js,console
const source = Rx.Observable.range(0, 5).do(x => console.log('do' + x)).controlled();
source.subscribe(x => console.log(x));
setTimeout(() => {
console.log('requesting');
source.request(2);
}, 1000);
您会注意到 Observable.range(0, 5)
中的所有五个值都由 do
立即发出 ... 然后一秒(1000 毫秒)暂停在你得到你的两个值之前。
所以,这真的是背压控制的错觉。最后,该运算符中有一个无界缓冲区。一个数组,它正在收集 Observable "above" 发送的所有内容并等待您通过调用 request(n)
.
RxJS 5.0.0-beta.2 复制 controlled
在回答这个问题时,controlled
运算符在 RxJS 5 中不存在。这是出于以下几个原因:1. 没有请求,以及 2. 它的名称显然令人困惑(因此Whosebug 上的这个问题)
如何复制 RxJS 5 中的行为(目前):http://jsbin.com/metuyab/1/edit?html,js,console
// A subject we'll use to zip with the source
const controller = new Rx.Subject();
// A request function to next values into the subject
function request(count) {
for (let i = 0; i < count; i++) {
controller.next(count);
}
}
// We'll zip our source with the subject, we don't care about what
// comes out of the Subject, so we'll drop that.
const source = Rx.Observable.range(0, 5).zip(controller, (x, _) => x);
// Same effect as above Rx 4 example
source.subscribe(x => console.log(x));
// Same effect as above Rx 4 example
request(3);
背压控制
目前 "real backpressure control",一个解决方案是 promise 的迭代器。尽管 IoP 并非没有问题,一方面,每个回合都有一个对象分配。每个值都有一个与之关联的 Promise。另一方面,取消不存在,因为它是承诺。
一个更好的、基于 Rx 的方法是让一个 Subject "feeds" 位于你的可观察链的顶部,而你在其余部分进行组合。
像这样:http://jsbin.com/qeqaxo/2/edit?js,console
// start with 5 values
const controller = new Rx.BehaviorSubject(5);
// some observable source, in this case, an interval.
const source = Rx.Observable.interval(100)
const controlled = controller.flatMap(
// map your count into a set of values
(count) => source.take(count),
// additional mapping for metadata about when the block is done
(count, value, _, index) => {
return { value: value, done: count - index === 1 };
})
// when the block is done, request 5 more.
.do(({done}) => done && controller.next(5))
// we only care about the value for output
.map(({value}) => value);
// start our subscription
controlled.subscribe(x => {
console.log(x)
});
...我们也有一些计划在不久的将来实现具有真正背压控制的可流动可观察类型。对于这种情况,那会更令人兴奋和更好。
您可以通过 publishing the observable. The published observable will only be started after calling connect 将可观察对象的开始与订阅分开。
请注意,所有订阅者将共享对可观察序列的单一订阅。
var published = Observable.of(42).publish();
// subscription does not start the observable sequence
published.subscribe(value => console.log('received: ', value));
// connect starts the sequence; subscribers will now receive values
published.connect();