Redux Observable: как вернуть действие из обратного вызова?

Я использую библиотеку WebRTC, которая имеет очень специфический API. peerConnection.setRemoteDescription Второй аргумент метода должен быть обратным вызовом, когда он завершает установку удаленного описания:

Это одна из моих функций-оболочек для моего класса WebRTC:

export function setRemoteSdp(peerConnection, sdp, callback) {
  if (!sdp) return;
  return peerConnection.setRemoteDescription(
    new RTCSessionDescription(sdp),
    callback, // <-------------
  );
}

И это набросок того, что я хочу сделать:

function receivedSdp(action$, store) {
  return action$.ofType(VideoStream.RECEIVED_SDP)
    .mergeMap(action => {
      const {peerConnection} = store.getState().videoStreams;
      const {sdp} = action.payload;

      return WebRTC.setRemoteSdp(peerConnection, sdp, () => {
        return myReducer.myAction(); // <------ return action as the callback
      })
    })
};

Это не работает, так как я не возвращаю Observable. Есть ли способ сделать это?

PS это API WebRTC: https://github.com/oney/react-native-webrtc/blob/master/RTCPeerConnection.js#L176

2 ответа

Решение

Так что проблема в том, что setRemoteSdp не возвращает наблюдаемое время myReducer.myAction() и это Обсерватория вы хотите объединить?

Ты можешь использовать Observable.create и обернуть WebRTC.setRemoteSdp вызов:

.mergeMap(action => {
  return Observable.create(observer => {
    WebRTC.setRemoteSdp(peerConnection, sdp, () => {
      observer.next(myReducer.myAction());
      observer.complete();
    })
  });
}
.mergeAll()

Observable.create возвращает наблюдаемое, которое испускает другое наблюдаемое из myReducer.myAction(), Теперь у меня есть так называемый высший порядок, который я хочу сгладить, используя mergeAll() (concatAll будет работать так же).

Ответ Мартина правильный об использовании Observable.create или же new Observable- то же самое (за исключением того, что мне не понятно, зачем вам mergeAll() так как mergeMap сгладит?)

В качестве бонуса вы также можете использовать Observable.bindCallback за это.

// bindCallback is a factory factory, it creates a function that
// when called with any arguments will return an Observable that
// wraps setRemoteSdp, handling the callback portion for you.
// I'm using setRemoteSdp.bind(WebRTC) because I don't know
// if setRemoteSdp requires its calling context to be WebRTC
// so it's "just in case". It might not be needed.
const setRemoteSdpObservable = Observable.bindCallback(WebRTC.setRemoteSdp.bind(WebRTC));

setRemoteSdpObservable(peerConnection, sdp)
  .subscribe(d => console.log(d));

Использование внутри вашей эпопеи будет что-то вроде этого

// observables are lazy, so defining this outside of our epic
// is totally cool--it only sets up the factory
const setRemoteSdpObservable = Observable.bindCallback(WebRTC.setRemoteSdp.bind(WebRTC));

function receivedSdp(action$, store) {
  return action$.ofType(VideoStream.RECEIVED_SDP)
    .mergeMap(action => {
      const {peerConnection} = store.getState().videoStreams;
      const {sdp} = action.payload;

      return setRemoteSdpObservable(peerConnection)
        .map(result => myReducer.myAction());
    })
};

Вы можете использовать это для создания Observable оболочек для всех API WebRTC.

Другие вопросы по тегам