Node.js 试图让我自己的RxJs可以被观察到

Node.js 试图让我自己的RxJs可以被观察到,node.js,rxjs,Node.js,Rxjs,我正在尝试转换一个现有的API来使用RxJS。。。对node来说是相当新的,对RxJs来说也是非常新的,所以请耐心听我说 我有一个现有的API(getNextMessage),它要么阻塞(异步),要么通过一个节点样式(err,val)回调返回一个新的项或错误,当something变得可用时 所以它看起来像: getNextMessage(nodeStyleCompletionCallback) 您可以将getNextMessage想象为http请求,它将在将来服务器响应时完成,但您确实需要在收到

我正在尝试转换一个现有的API来使用RxJS。。。对node来说是相当新的,对RxJs来说也是非常新的,所以请耐心听我说

我有一个现有的API(getNextMessage),它要么阻塞(异步),要么通过一个节点样式(err,val)回调返回一个新的项或错误,当something变得可用时

所以它看起来像:

getNextMessage(nodeStyleCompletionCallback)

您可以将getNextMessage想象为http请求,它将在将来服务器响应时完成,但您确实需要在收到消息后再次调用getNextMessage,以继续从服务器获取新项目

因此,为了使它成为一个可观察的集合,我必须让RxJs继续调用我的getNextMessage函数,直到用户被释放()

基本上,我正在尝试创建自己的RxJs可观察集合

问题是:

  • 我不知道如何使subscriber.dispose()永远杀死async.forever
  • 首先,我可能不应该永远使用async.forever
  • 我甚至不确定我是否应该为每条消息“完成”——这不应该在序列的末尾吗
  • 我希望最终消除使用fromNodeCallback的需要,以获得一个可观察的第一类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();
        }
    );
    

    所以我可能会这么做

    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');       }
      );
    

    我意识到这已经有一年多的历史了,但我认为更好的解决方案是使用递归调度:

    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);
    });
    

    查看一个工作示例

    非常感谢!我自己也算出了其中的一半,并且有点让它工作起来了,尽管我还没有摆脱async。现在我可以建立我自己的第一类观测,这是一个美丽的世界。顺便说一句,这是一个很好的例子——应该放在RxJs文档的某个地方。再次感谢。