簡體   English   中英

從Observable上的subcribe獲取返回值

[英]Get return value from subcribe on Observable

使用RxJS 5.0.0-rc.1 ,我試圖通過使用yield.next()交換數據,以類似於生成器/迭代器的工作方式來傳達我的ObserverObservable 目的是獲取對.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));
});

它更有意義嗎?

發電機和可觀測量之間確實存在相似之處。 正如您在此處所看到的,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運算符可以提供幫助。 要了解其行為,請查看文檔以及SO上的以下答案,以獲取在具體情況下使用的示例:

基本上, expand允許您向下游發出值並在生產者中同時反饋該值。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM