69392

Redux Observable: How to return an action from a callback?

Question:

I'm using the WebRTC library which has a very specific API. The peerConnection.setRemoteDescription method's 2nd argument is supposed to be a callback for when it finishes setting the remote description:

This is one of my wrapper functions for my WebRTC class:

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

And this is a sketch of what I want to do:

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

This doesn't work since I'm not returning an Observable. Is there a way to do this?

P.S. this is the WebRTC API: <a href="https://github.com/oney/react-native-webrtc/blob/master/RTCPeerConnection.js#L176" rel="nofollow">https://github.com/oney/react-native-webrtc/blob/master/RTCPeerConnection.js#L176</a>

Answer1:

So the problem is that setRemoteSdp doesn't return an Observable while myReducer.myAction() does and that's the Observable you want to merge?

You can use Observable.create and wrap the WebRTC.setRemoteSdp call:

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

The Observable.create returns an Observable that emits another Observable from myReducer.myAction(). Now I have in fact so-called higher-order that I want to flatten using mergeAll() (concatAll would work as well).

Answer2:

martin's answer is correct about using Observable.create or new Observable--same thing (except it's not clear to me why you need the mergeAll() since the mergeMap will flatten?)

As a bonus, you could also use Observable.bindCallback for this.

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

Usage inside your epic would be something like this

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

You could use this to create Observable wrappers for all the WebRTC apis.

Recommend

  • How to Return Helpers Text as data from Action
  • Parse elements from href tags
  • Change HTTP URL in Worklight adapter
  • Getter Property (without property and setter) Access Via ValueStack
  • Assigning actions to a variable
  • Null Pointer Exception when trying to send message from one activity to another
  • Symfony2 - Composer class loader instance in controller
  • Passing Props from State to Child
  • javascript / jquery scope differences between jQuery.each and normal for loop?
  • Contact form problem - I do receive messages, but no contents (blank page)
  • How to handle Back Button to remove current fragment In MvvmCross
  • IDX10503: Signature validation failed
  • QueryString id parameter not being used
  • Set the default timezone in symfony
  • How to integrate Paytm with Codeigniter
  • calling a fragment from fragment
  • Regex for URL rewrite with optional query string parameters
  • Mocha throws unexpected token error for ES6 object spread operator
  • What is this error in fortran and how to stop the program when it occurs?
  • Action Pack components in Rails
  • multidatatrigger with multibinding in ControlTemplate.Triggers
  • Can you pass an array from javascript to asp.net mvc controller action without using a form?
  • redirect_to root_url and return unless @user.activated
  • Getting the scrolling offset when storing coordinates
  • didUpdatePushCredentials not get called
  • Bootstrap (v3.3.4) glyphicons not displayed in IE when refresh page (F5)
  • Implementing “partial void” in VB
  • Sending HTML Form Data to Spring REST Web Service
  • Connect .sks to skscene.h
  • C: Incompatible pointer type initializing
  • AES padding and writing the ciphertext to a disk file
  • VS2008 Enable C++ Exception with SEH
  • what is the difference between the asp.net mvc application and asp.net web application
  • Weird JavaScript statement, what does it mean?
  • Do I've to free mysql result after storing it?
  • SQL merge duplicate rows and join values that are different
  • FormattedException instead of throw new Exception(string.Format(…)) in .NET
  • How to Embed XSL into XML
  • UserPrincipal.Current returns apppool on IIS
  • Conditional In-Line CSS for IE and Others?