Last active
August 29, 2015 14:27
-
-
Save hedgerworkco/ef4e4e24704dfa5fd03b to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
["^ ","posts",["~#iM",["postsById",["^1",["Stop-Trying-to-Catch-Me",["^ ","date",20150407,"shorturl","Stop-Trying-to-Catch-Me","title","Stop Trying to Catch Me","published",true,"abstract","I'm probably going to regret this, but this post is about promises. There are a few details that I'd like to spell out so I can point people to this post instead of repeating myself. Here are a few reasons why I don't like promises.","content","I'm probably going to regret this, but this post is about promises. There are a few details that I'd like to spell out so I can point people to this post instead of repeating myself. This is not a hyperbolic post like [Radical Statements about the Mobile Web](http://jlongster.com/Radical-Statements-about-the-Mobile-Web), which I sort of regret posting. In that post I was just yelling from a mountaintop, which isn't very helpful.\n\nI humbly submit these points as reasons why I don't like promises, with full realization that the ship has sailed and nothing is going to change.\n\nFirst, let's talk about `try`/`catch`. The problem with exception handling in JavaScript is that it's too aggresive. Consider the following code:\n\n```js\ntry {\n var result = foo(getValue());\n}\ncatch(e) {\n // handle error from `foo` \n}\n```\n\nWe've accidentally captured the `getValue()` expression within this handler, so any error within `getValue` is captured. This is how exceptions work, of course, but it's made worse in JavaScript because a *simple typo* becomes an exception.\n\nExceptions are meant to be just that, exceptional. In most other languages, many typo-style errors are caught at compile-time, even in dynamic languages like Clojure. But in JavaScript, with the above code, if I was happily hacking away within `getValue` and I typed `fucn()` instead of `func()`, it gets caught and treated as an exception here.\n\nI don't like how easy it is to get tripped up `try`/`catch`. We could turn the above code into this:\n\n```js\ntry {\n var result = foo(getValue());\n}\ncatch(e) {\n if(e instanceof FooError) {\n // handle error from `foo`\n return;\n }\n throw e;\n}\n```\n\nNot only is this a ton of boilerplate, but it breaks an important feature of JavaScript debuggers: break on exception. If you have break on exception enabled, and you make an error inside `getValue`, it now pauses on the `throw` in the above code instead of inside `getValue` where you actually made the mistake.\n\nSo it's crazy to me that promises want to apply this behavior to async code and wrap *everything* in a `try`/`catch`. Break on exception is permanently broken now, and we have to go through all sorts of contortions and backflips to get back to reasonable debugging environment. All because it wraps code in `try`/`catch` by default.\n\nI don't care about awkward `.then()` syntax. I don't mind automatic error propagation. I don't care having to call `.done()` on a promise chain. I don't care about losing the stack (which is inherent in any async work).\n\nI care that promises grab *all* errors, just like `try`/`catch`. The cost of a simple typo is greatly magnified. When you do async work in most other systems, you deal with errors *pertaining to your async call*. If I make an HTTP request, I want the network error to automatically bubble up the promise chain. I don't want anything unrelated to the async work to bubble up. I don't care about it.\n\nI should be able to reject a promise with an error, and it bubbles up. But I want to make stupid typo errors and have them appear as normal errors, not caught by promises. Don't run everything in `try`/`catch`.\n\n### Oh, and about `async`/`await`\n\nES7 proposes async functions for doing async work. A lot of people are extremely excited about it, and honestly I don't get the excitement. Async functions are only pretty generators with promises:\n\n```js\nvar asyncFunction = Task(function*() {\n var result = yield fetch(url);\n return process(result);\n}):\n```\n\n`fetch` returns a promise. With async functions, it would look like this:\n\n```js\nasync function asyncFunction() {\n var result = await fetch(url);\n return process(result);\n}\n```\n\nOk, so that is nicer, and `asyncFunction` is hoisted (I think) like a normal function would be. It's cool, I just don't understand why everyone is *so* excited about a simple syntactic improvement.\n\nEspecially when we still have all the problems with promises. For example, some top-level promise code now looks like:\n\n```js\nasync function run() {\n console.log(await asyncFunction());\n}\n\nrun();\n```\n\nA newbie to JavaScript will write that code, and be totally bewildered when nothing happens. They have no idea that they made a typo in `asyncFunction`, and it takes them a while to learn that `run` actually returns a promise.\n\nHere a few ideas I have:\n\n1. Allow `run` to mark itself as a top-level function somehow that automatically throws errors\n2. Now that we have #1, when an error happens inside a promise, the JS engine check the promise chain to see if the error should immediately throw or not. It should immediately throw (as a *normal error*) if there is a top-level async function at the beginning of the promise chain.\n\nOk, so that's really just one idea. Native `async`/`await` syntax could potentitally help here, if we are willing to think outside of promises.\n\n### You're Writing An Angry Tweet Right Now, Aren't You?\n\nWe are discussing error handling within the [js-csp](https://github.com/ubolonton/js-csp) project, which implements go-style channels. Most likely we are going to propogate errors, but only ones that comes down channels. I've been trying this out for a while and I love it.\n\nI'm not going to spend time here convincing you to use js-csp, I just wanted to offer a solution instead of just complaining.\n\nHopefully I explained this well. I don't expect anything to change. I think my idea about async/await is pretty cool, so I hope someone looks into it.\n","tags",["promise"]]]],"postsByQuery",["^1",[]],"postsByQueryName",["^1",[]]]],"asyncRequests",["^1",["errors",["~#iL",[["^ ","message","Error: must be authorized user for this action","action",["^ ","type","UPDATE_POST","post",["^ ","^2",20150407,"^3","Stop-Trying-to-Catch-Me","^4","Stop Trying to Catch Me","^5",true,"^6","YOU THINK YOU CAN EDIT THIS??? well try saving it.","^7","I'm probably going to regret this, but this post is about promises. There are a few details that I'd like to spell out so I can point people to this post instead of repeating myself. This is not a hyperbolic post like [Radical Statements about the Mobile Web](http://jlongster.com/Radical-Statements-about-the-Mobile-Web), which I sort of regret posting. In that post I was just yelling from a mountaintop, which isn't very helpful.\n\nI humbly submit these points as reasons why I don't like promises, with full realization that the ship has sailed and nothing is going to change.\n\nFirst, let's talk about `try`/`catch`. The problem with exception handling in JavaScript is that it's too aggresive. Consider the following code:\n\n```js\ntry {\n var result = foo(getValue());\n}\ncatch(e) {\n // handle error from `foo` \n}\n```\n\nWe've accidentally captured the `getValue()` expression within this handler, so any error within `getValue` is captured. This is how exceptions work, of course, but it's made worse in JavaScript because a *simple typo* becomes an exception.\n\nExceptions are meant to be just that, exceptional. In most other languages, many typo-style errors are caught at compile-time, even in dynamic languages like Clojure. But in JavaScript, with the above code, if I was happily hacking away within `getValue` and I typed `fucn()` instead of `func()`, it gets caught and treated as an exception here.\n\nI don't like how easy it is to get tripped up `try`/`catch`. We could turn the above code into this:\n\n```js\ntry {\n var result = foo(getValue());\n}\ncatch(e) {\n if(e instanceof FooError) {\n // handle error from `foo`\n return;\n }\n throw e;\n}\n```\n\nNot only is this a ton of boilerplate, but it breaks an important feature of JavaScript debuggers: break on exception. If you have break on exception enabled, and you make an error inside `getValue`, it now pauses on the `throw` in the above code instead of inside `getValue` where you actually made the mistake.\n\nSo it's crazy to me that promises want to apply this behavior to async code and wrap *everything* in a `try`/`catch`. Break on exception is permanently broken now, and we have to go through all sorts of contortions and backflips to get back to reasonable debugging environment. All because it wraps code in `try`/`catch` by default.\n\nI don't care about awkward `.then()` syntax. I don't mind automatic error propagation. I don't care having to call `.done()` on a promise chain. I don't care about losing the stack (which is inherent in any async work).\n\nI care that promises grab *all* errors, just like `try`/`catch`. The cost of a simple typo is greatly magnified. When you do async work in most other systems, you deal with errors *pertaining to your async call*. If I make an HTTP request, I want the network error to automatically bubble up the promise chain. I don't want anything unrelated to the async work to bubble up. I don't care about it.\n\nI should be able to reject a promise with an error, and it bubbles up. But I want to make stupid typo errors and have them appear as normal errors, not caught by promises. Don't run everything in `try`/`catch`.\n\n### Oh, and about `async`/`await`\n\nES7 proposes async functions for doing async work. A lot of people are extremely excited about it, and honestly I don't get the excitement. Async functions are only pretty generators with promises:\n\n```js\nvar asyncFunction = Task(function*() {\n var result = yield fetch(url);\n return process(result);\n}):\n```\n\n`fetch` returns a promise. With async functions, it would look like this:\n\n```js\nasync function asyncFunction() {\n var result = await fetch(url);\n return process(result);\n}\n```\n\nOk, so that is nicer, and `asyncFunction` is hoisted (I think) like a normal function would be. It's cool, I just don't understand why everyone is *so* excited about a simple syntactic improvement.\n\nEspecially when we still have all the problems with promises. For example, some top-level promise code now looks like:\n\n```js\nasync function run() {\n console.log(await asyncFunction());\n}\n\nrun();\n```\n\nA newbie to JavaScript will write that code, and be totally bewildered when nothing happens. They have no idea that they made a typo in `asyncFunction`, and it takes them a while to learn that `run` actually returns a promise.\n\nHere a few ideas I have:\n\n1. Allow `run` to mark itself as a top-level function somehow that automatically throws errors\n2. Now that we have #1, when an error happens inside a promise, the JS engine check the promise chain to see if the error should immediately throw or not. It should immediately throw (as a *normal error*) if there is a top-level async function at the beginning of the promise chain.\n\nOk, so that's really just one idea. Native `async`/`await` syntax could potentitally help here, if we are willing to think outside of promises.\n\n### You're Writing An Angry Tweet Right Now, Aren't You?\n\nWe are discussing error handling within the [js-csp](https://github.com/ubolonton/js-csp) project, which implements go-style channels. Most likely we are going to propogate errors, but only ones that comes down channels. I've been trying this out for a while and I love it.\n\nI'm not going to spend time here convincing you to use js-csp, I just wanted to offer a solution instead of just complaining.\n\nHopefully I explained this well. I don't expect anything to change. I think my idea about async/await is pretty cool, so I hope someone looks into it.\n","^8",["promise"]],"@@dispatch/seqId",7,"status","error","value","Error: must be authorized user for this action"]],["^ ","^;","Error: must be authorized user for this action","^<",["^ ","^=","UPDATE_POST","^>",["^ ","^2",20150407,"^3","Stop-Trying-to-Catch-Me","^4","Stop Trying to Catch Me","^5",true,"^6","YOU THINK YOU CAN EDIT THIS??? well try saving it.","^7","I'm probably going to regret this, but this post is about promises. There are a few details that I'd like to spell out so I can point people to this post instead of repeating myself. This is not a hyperbolic post like [Radical Statements about the Mobile Web](http://jlongster.com/Radical-Statements-about-the-Mobile-Web), which I sort of regret posting. In that post I was just yelling from a mountaintop, which isn't very helpful.\n\nI humbly submit these points as reasons why I don't like promises, with full realization that the ship has sailed and nothing is going to change.\n\nFirst, let's talk about `try`/`catch`. The problem with exception handling in JavaScript is that it's too aggresive. Consider the following code:\n\n```js\ntry {\n var result = foo(getValue());\n}\ncatch(e) {\n // handle error from `foo` \n}\n```\n\nWe've accidentally captured the `getValue()` expression within this handler, so any error within `getValue` is captured. This is how exceptions work, of course, but it's made worse in JavaScript because a *simple typo* becomes an exception.\n\nExceptions are meant to be just that, exceptional. In most other languages, many typo-style errors are caught at compile-time, even in dynamic languages like Clojure. But in JavaScript, with the above code, if I was happily hacking away within `getValue` and I typed `fucn()` instead of `func()`, it gets caught and treated as an exception here.\n\nI don't like how easy it is to get tripped up `try`/`catch`. We could turn the above code into this:\n\n```js\ntry {\n var result = foo(getValue());\n}\ncatch(e) {\n if(e instanceof FooError) {\n // handle error from `foo`\n return;\n }\n throw e;\n}\n```\n\nNot only is this a ton of boilerplate, but it breaks an important feature of JavaScript debuggers: break on exception. If you have break on exception enabled, and you make an error inside `getValue`, it now pauses on the `throw` in the above code instead of inside `getValue` where you actually made the mistake.\n\nSo it's crazy to me that promises want to apply this behavior to async code and wrap *everything* in a `try`/`catch`. Break on exception is permanently broken now, and we have to go through all sorts of contortions and backflips to get back to reasonable debugging environment. All because it wraps code in `try`/`catch` by default.\n\nI don't care about awkward `.then()` syntax. I don't mind automatic error propagation. I don't care having to call `.done()` on a promise chain. I don't care about losing the stack (which is inherent in any async work).\n\nI care that promises grab *all* errors, just like `try`/`catch`. The cost of a simple typo is greatly magnified. When you do async work in most other systems, you deal with errors *pertaining to your async call*. If I make an HTTP request, I want the network error to automatically bubble up the promise chain. I don't want anything unrelated to the async work to bubble up. I don't care about it.\n\nI should be able to reject a promise with an error, and it bubbles up. But I want to make stupid typo errors and have them appear as normal errors, not caught by promises. Don't run everything in `try`/`catch`.\n\n### Oh, and about `async`/`await`\n\nES7 proposes async functions for doing async work. A lot of people are extremely excited about it, and honestly I don't get the excitement. Async functions are only pretty generators with promises:\n\n```js\nvar asyncFunction = Task(function*() {\n var result = yield fetch(url);\n return process(result);\n}):\n```\n\n`fetch` returns a promise. With async functions, it would look like this:\n\n```js\nasync function asyncFunction() {\n var result = await fetch(url);\n return process(result);\n}\n```\n\nOk, so that is nicer, and `asyncFunction` is hoisted (I think) like a normal function would be. It's cool, I just don't understand why everyone is *so* excited about a simple syntactic improvement.\n\nEspecially when we still have all the problems with promises. For example, some top-level promise code now looks like:\n\n```js\nasync function run() {\n console.log(await asyncFunction());\n}\n\nrun();\n```\n\nA newbie to JavaScript will write that code, and be totally bewildered when nothing happens. They have no idea that they made a typo in `asyncFunction`, and it takes them a while to learn that `run` actually returns a promise.\n\nHere a few ideas I have:\n\n1. Allow `run` to mark itself as a top-level function somehow that automatically throws errors\n2. Now that we have #1, when an error happens inside a promise, the JS engine check the promise chain to see if the error should immediately throw or not. It should immediately throw (as a *normal error*) if there is a top-level async function at the beginning of the promise chain.\n\nOk, so that's really just one idea. Native `async`/`await` syntax could potentitally help here, if we are willing to think outside of promises.\n\n### You're Writing An Angry Tweet Right Now, Aren't You?\n\nWe are discussing error handling within the [js-csp](https://github.com/ubolonton/js-csp) project, which implements go-style channels. Most likely we are going to propogate errors, but only ones that comes down channels. I've been trying this out for a while and I love it.\n\nI'm not going to spend time here convincing you to use js-csp, I just wanted to offer a solution instead of just complaining.\n\nHopefully I explained this well. I don't expect anything to change. I think my idea about async/await is pretty cool, so I hope someone looks into it.\n","^8",["promise"]],"^?",8,"^@","error","^A","Error: must be authorized user for this action"]]]],"openRequests",["^:",[]]]],"route",["^ ","^4","James Long","className","edit","path","/edit/Stop-Trying-to-Catch-Me","user",["^ ","name","jlongster","admin",true]],"editor",["^ ","showSettings",true,"showPreview",false],"__localState",["^ ",".1",["^ ","^>",["^ ","^2",20150407,"^3","Stop-Trying-to-Catch-Me","^4","Stop Trying to Catch Me","^5",true,"^6","YOU THINK YOU CAN EDIT THIS??? well try saving it.","^7","I'm probably going to regret this, but this post is about promises. There are a few details that I'd like to spell out so I can point people to this post instead of repeating myself. This is not a hyperbolic post like [Radical Statements about the Mobile Web](http://jlongster.com/Radical-Statements-about-the-Mobile-Web), which I sort of regret posting. In that post I was just yelling from a mountaintop, which isn't very helpful.\n\nI humbly submit these points as reasons why I don't like promises, with full realization that the ship has sailed and nothing is going to change.\n\nFirst, let's talk about `try`/`catch`. The problem with exception handling in JavaScript is that it's too aggresive. Consider the following code:\n\n```js\ntry {\n var result = foo(getValue());\n}\ncatch(e) {\n // handle error from `foo` \n}\n```\n\nWe've accidentally captured the `getValue()` expression within this handler, so any error within `getValue` is captured. This is how exceptions work, of course, but it's made worse in JavaScript because a *simple typo* becomes an exception.\n\nExceptions are meant to be just that, exceptional. In most other languages, many typo-style errors are caught at compile-time, even in dynamic languages like Clojure. But in JavaScript, with the above code, if I was happily hacking away within `getValue` and I typed `fucn()` instead of `func()`, it gets caught and treated as an exception here.\n\nI don't like how easy it is to get tripped up `try`/`catch`. We could turn the above code into this:\n\n```js\ntry {\n var result = foo(getValue());\n}\ncatch(e) {\n if(e instanceof FooError) {\n // handle error from `foo`\n return;\n }\n throw e;\n}\n```\n\nNot only is this a ton of boilerplate, but it breaks an important feature of JavaScript debuggers: break on exception. If you have break on exception enabled, and you make an error inside `getValue`, it now pauses on the `throw` in the above code instead of inside `getValue` where you actually made the mistake.\n\nSo it's crazy to me that promises want to apply this behavior to async code and wrap *everything* in a `try`/`catch`. Break on exception is permanently broken now, and we have to go through all sorts of contortions and backflips to get back to reasonable debugging environment. All because it wraps code in `try`/`catch` by default.\n\nI don't care about awkward `.then()` syntax. I don't mind automatic error propagation. I don't care having to call `.done()` on a promise chain. I don't care about losing the stack (which is inherent in any async work).\n\nI care that promises grab *all* errors, just like `try`/`catch`. The cost of a simple typo is greatly magnified. When you do async work in most other systems, you deal with errors *pertaining to your async call*. If I make an HTTP request, I want the network error to automatically bubble up the promise chain. I don't want anything unrelated to the async work to bubble up. I don't care about it.\n\nI should be able to reject a promise with an error, and it bubbles up. But I want to make stupid typo errors and have them appear as normal errors, not caught by promises. Don't run everything in `try`/`catch`.\n\n### Oh, and about `async`/`await`\n\nES7 proposes async functions for doing async work. A lot of people are extremely excited about it, and honestly I don't get the excitement. Async functions are only pretty generators with promises:\n\n```js\nvar asyncFunction = Task(function*() {\n var result = yield fetch(url);\n return process(result);\n}):\n```\n\n`fetch` returns a promise. With async functions, it would look like this:\n\n```js\nasync function asyncFunction() {\n var result = await fetch(url);\n return process(result);\n}\n```\n\nOk, so that is nicer, and `asyncFunction` is hoisted (I think) like a normal function would be. It's cool, I just don't understand why everyone is *so* excited about a simple syntactic improvement.\n\nEspecially when we still have all the problems with promises. For example, some top-level promise code now looks like:\n\n```js\nasync function run() {\n console.log(await asyncFunction());\n}\n\nrun();\n```\n\nA newbie to JavaScript will write that code, and be totally bewildered when nothing happens. They have no idea that they made a typo in `asyncFunction`, and it takes them a while to learn that `run` actually returns a promise.\n\nHere a few ideas I have:\n\n1. Allow `run` to mark itself as a top-level function somehow that automatically throws errors\n2. Now that we have #1, when an error happens inside a promise, the JS engine check the promise chain to see if the error should immediately throw or not. It should immediately throw (as a *normal error*) if there is a top-level async function at the beginning of the promise chain.\n\nOk, so that's really just one idea. Native `async`/`await` syntax could potentitally help here, if we are willing to think outside of promises.\n\n### You're Writing An Angry Tweet Right Now, Aren't You?\n\nWe are discussing error handling within the [js-csp](https://github.com/ubolonton/js-csp) project, which implements go-style channels. Most likely we are going to propogate errors, but only ones that comes down channels. I've been trying this out for a while and I love it.\n\nI'm not going to spend time here convincing you to use js-csp, I just wanted to offer a solution instead of just complaining.\n\nHopefully I explained this well. I don't expect anything to change. I think my idea about async/await is pretty cool, so I hope someone looks into it.\n","^8",["promise"]],"validationError",null]]] |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment