- From: Jan-Ivar Bruaroey <jib@mozilla.com>
- Date: Thu, 02 Oct 2014 10:09:51 -0400
- To: Harald Alvestrand <harald@alvestrand.no>, public-media-capture@w3.org
- Message-ID: <542D5CAF.4030402@mozilla.com>
On 10/2/14, 5:00 AM, Harald Alvestrand wrote: > On 10/01/2014 10:05 PM, Jan-Ivar Bruaroey wrote: >> First, here's a fiddle [2] showing how promises handle errors correctly: >> >> >> <div id="log"></div> >> >> var div = document.getElementById("log"); >> var log = msg => (div.innerHTML = div.innerHTML + msg + "<br>"); >> >> new Promise(resolve => resolve()) >> .then(() => log("success1"), () => log("fail1")) >> .then(() => { >> log("success2a"); >> barf; >> log("success2b"); >> }, () => log("fail2")) >> .then(() => log("success3"), () => log("fail3")) >> .then(() => log("success4"), () => log("fail4")) >> .then(() => log("success5"), () => log("fail5")) >> .catch(() => log("failure")); >> > > Now this is interesting, not because of its relationship to > getUserMedia, but because of what it says about the additional > functionality of promises.... > > In the callback world, we insist that gUM calls *one* function, *once*. > In the promises world, we say that a promise can call *any number* of > functions - and which ones get called is not going to be obvious. That's a mischaracterization, so I fear my example is confusing. Whether you use promises or callbacks, gUM only calls *one* success function, but that consumer function typically launches everything that follows, including potentially more asynchronous steps like peerConnection.createOffer and so on. That's a chain whether you use promises or callbacks, no difference. What's different is that with the callback pattern, it's near impossible to NOT react with anything but total failure of all subsequent steps (I think we presume this to be OK in gUM/WebRTC as it tends to be OK in simple demos). In other words, there's no room for handling errors along the way like you can in synchronous code using try/catch. Maybe this helps: My example is uncommon, because people typically DON'T put in rejection handlers for every promise step, because that's analogous to using try/catch on EVERY statement (promise.catch(f) is after all an alias for promise.then(null, f): // Synchronous code analogy to my very non-gUM example above try { step1(); } catch (e) { log ("fail1"); } try { log("success1"); step2(); } catch (e) { log ("fail2"); } try { log("success2a"); barf; log("success2b"); } catch (e) { log("fail3"); } try { log("success3"); step4(); } catch (e) { log ("fail4"); } try { log("success4"); step5(); } catch (e) { log ("fail4"); } try { log("success5"); } catch (e) { log ("failure"); } Which you would never do in most gUM/WebRTC demos! A more common thing is to omit rejection-handlers, letting errors "bubble up", just like people don't normally try/catch every statement). Here's that fiddle [1]: <div id="log"></div> var div = document.getElementById("log"); var log = msg => (div.innerHTML = div.innerHTML + msg + "<br>"); new Promise(resolve => resolve()) .then(() => log("success1")) .then(() => { log("success2a"); barf; log("success2b"); }) .then(() => log("success3")) .then(() => log("success4")) .then(() => log("success5")) .catch(() => log("failure")); This produces what you probably expected: success1 success2a failure And matches the pattern useful for simple gUM/webRTC demos. > On the other hand, success4 got called exactly as expected, despite > the fact that something went boom somewhere in the processing. So if > you want to be sure 2 success handlers get called on success, you have > to do: > > <promise-generator> > .then(success1, failure1) > .then(null, failure-in-handler-set-1) > .then(success2, failure2) > .catch(failure-in-handler-set-2) > > That's not necessarily a bad thing. But it's not unsubtle either. Again I think you're taking the wrong lesson from my perhaps overly complicated example. In practice I think you'll see little reason to distinguish between the synchronous setup of an async function - like say peerConnection.createOffer - and the asynchronous part that follows, because if the setup fails then likely the async call wont go well either, but you're welcome to split things into as many parts as you wish. Again, for gUM and WebRTC, where each step tends to rely on the success of the previous step, the fiddle below is more appropriate. It just doesn't highlight all possibilities with error handling. .: Jan-Ivar :. [1] Firefox: http://jsfiddle.net/jib1/0h2jon2L - Others: http://jsfiddle.net/jib1/9dvbxmoh
Received on Thursday, 2 October 2014 14:10:24 UTC