- From: Jan-Ivar Bruaroey <jib@mozilla.com>
- Date: Sat, 20 Sep 2014 01:54:39 -0400
- To: "public-webrtc@w3.org" <public-webrtc@w3.org>
If you don't care for promises, their minimal impact is: - navigator.getUserMedia(constraints, function(stream) { + mediaDevices.getUserMedia(constraints).then(function(stream) { video.srcObject = stream; video.play(); - }, function (err) { + }).catch(function (err) { console.log(err.message); }); But you'd be missing out by stopping there, as I believe they have a lot more to offer WebRTC. To illustrate, I've rewritten our local-loop replaceTrack demo-script to use a promises polyfill that works in Firefox Nightly [1]. Here's a cleaned-up excerpt: function call(pc, signal) { return mediaDevices.getUserMedia(myrequest) .then(video => { localvideo1.srcObject = video; localvideo1.play(); video1.getTracks().forEach(track => pc.addTrack(track, video)); return pc.createOffer(offer_options); }) .then(offer => pc.setLocalDescription(offer)) .then(() => signal.then(answer => pc.setRemoteDescription(answer))); } function pickup(pc, signal) { return (oneway.checked? new Promise(resolve => resolve()) : mediaDevices.getUserMedia(myrequest_reverse) .then(video => { localvideo2.srcObject = video; localvideo2.play(); video.getTracks().forEach(track => pc.addTrack(track, video)); })) .then(() => signal.then(offer => pc.setRemoteDescription(offer))) .then(() => pc.createAnswer(answer_options)) .then(answer => pc.setLocalDescription(answer)); } Promise.all([call(pc1, pc2.stable), pickup(pc2, pc1.haveLocalOffer)]) .then(() => log("HIP HIP HOORAY")) .catch(failed); // 1-line error handling This is a complete local-loop call. The two functions, call() and pickup(), may be a bit contrived, but illustrate that unlike most local-loop tests you've probably seen, each peer is set up asynchronously and in parallel, with only a signal sent across, much like in a remote call. Several things are going on here - which I will explain - and promises are used in three interesting ways: First, there's the promise-chains: then().then().then(). We start two chains in parallel and wait for both to complete with Promise.all. This is pretty straightforward promise-stuff, but powerful. Then, there's three new promises that I've added as read-only-attributes (yes!) to the peerConnection polyfill that trigger on signalingstate: pc.hasLocalOffer pc.hasRemoteOffer pc.stable Turns out promises can be used to track simple states. E.g. to make something happen when signalingstate changes to "has-local-offer", you just do: pc.hasLocalOffer.then(function(offer) { ... }); To make it more useful, I've made the fulfillment value be the offer (or answer depending), which means I can use them as the carrier 'signal' argument that gives the call() and pickup() functions the other peer's sdp when it becomes available. Lastly, my final use of promises was to fix an unfortunate race in local-loop calls. With the two peers less tightly coupled, I started seeing ICE failures. Turns out candidates were arriving before the other peer could receive them, and addIceCandidate was failing, complaining that it could not be called beforesetRemoteDescription. Is that by spec? To solve this, I relied again on the signalingstate promises: pc1.onicecandidate = obj => { pc2.haveRemoteOffer.then(() => { if (obj.candidate) { pc2.addIceCandidate(obj.candidate).catch(failed); } }); }; pc2.onicecandidate = obj => { pc1.stable.then(() => { if (obj.candidate) { pc1.addIceCandidate(obj.candidate).catch(failed); } }); }; Turns out promises can be used to queue function-calls. Calling then() multiple times on the same promise queues functions up to be executed in order later (or right away if the promise has already been resolved). This made it easy to subjugate addIceCandidate's timing-needs. So there you have it. Three uses of promises in the same API. I also enjoy that there is one line of error-handling in the whole thing. Feel free to have a look at the full test or take it for a spin: Comments welcome. [1] https://bug1033885.bugzilla.mozilla.org/attachment.cgi?id=8492552 .: Jan-Ivar :.
Received on Saturday, 20 September 2014 05:55:08 UTC