我试图将现有的API转换为与RxJS一起使用...对于节点来说是相当新的,对RxJ来说是新手,所以请耐心等待。
我有一个现有的API(getNextMessage),它可以阻止(异步),或者当某个东西可用时,通过节点样式(错误,val)回调返回一个新项或错误。
所以它看起来像:
getNextMessage(nodeStyleCompletionCallback);
您可以将getNextMessage视为一个http请求,将来会在服务器响应时完成,但是一旦收到消息,您需要再次调用getNextMessage,以便不断从服务器获取新项目。
所以,为了使它成为一个可观察的集合,我必须让RxJs继续调用我的getNextMessage函数,直到订阅者被处置();
基本上,我正在尝试创建自己的RxJs可观察集合。
问题是:
非常乐意帮助,谢谢!
这是我现有的代码:
var Rx = require('rx');
var port = require('../lib/port');
var async = require('async');
function observableReceive(portName)
{
var observerCallback;
var listenPort = new port(portName);
var disposed = false;
var asyncReceive = function(asyncCallback)
{
listenPort.getNextMessage(
function(error, json)
{
observerCallback(error, json);
if (!disposed)
setImmediate(asyncCallback);
}
);
}
return function(outerCallback)
{
observerCallback = outerCallback;
async.forever(asyncReceive);
}
}
var receive = Rx.Observable.fromNodeCallback(observableReceive('rxtest'));
var source = receive();
var subscription = source.forEach(
function (json)
{
console.log('receive completed: ' + JSON.stringify(json));
},
function (error) {
console.log("receive failed: " + error.toString());
},
function () {
console.log('Completed');
subscription.dispose();
}
);
答案 0 :(得分:14)
所以这可能就是我要做的事。
var Rx = require('Rx');
// This is just for kicks. You have your own getNextMessage to use. ;)
var getNextMessage = (function(){
var i = 1;
return function (callback) {
setTimeout(function () {
if (i > 10) {
callback("lawdy lawd it's ova' ten, ya'll.");
} else {
callback(undefined, i++);
}
}, 5);
};
}());
// This just makes an observable version of getNextMessage.
var nextMessageAsObservable = Rx.Observable.create(function (o) {
getNextMessage(function (err, val) {
if (err) {
o.onError(err);
} else {
o.onNext(val);
o.onCompleted();
}
});
});
// This repeats the call to getNextMessage as many times (11) as you want.
// "take" will cancel the subscription after receiving 11 items.
nextMessageAsObservable
.repeat()
.take(11)
.subscribe(
function (x) { console.log('next', x); },
function (err) { console.log('error', err); },
function () { console.log('done'); }
);
答案 1 :(得分:5)
我意识到这已经超过一年了,但我认为更好的解决方案是使用递归调度代替:
Rx.Observable.forever = function(next, scheduler) {
scheduler = scheduler || Rx.Scheduler.default,
//Internally wrap the the callback into an observable
next = Rx.Observable.fromNodeCallback(next);
return Rx.Observable.create(function(observer) {
var disposable = new Rx.SingleAssignmentDisposable(),
hasState = false;
disposable.setDisposable(scheduler.scheduleRecursiveWithState(null,
function(state, self) {
hasState && observer.onNext(state);
hasState = false;
next().subscribe(function(x){
hasState = true;
self(x);
}, observer.onError.bind(observer));
}));
return disposable;
});
};
这里的想法是,您可以在上一个项目完成后安排新项目。您调用next()
来调用传入的方法,当它返回一个值时,您可以安排下一个项目进行调用。
然后您可以这样使用它:
Rx.Observable.forever(getNextMessage)
.take(11)
.subscribe(function(message) {
console.log(message);
});
查看工作示例here