Proposal: Conditional `catch` in Promises

classic Classic list List threaded Threaded
9 messages Options
Reply | Threaded
Open this post in threaded view
|

Proposal: Conditional `catch` in Promises

Ayush Gupta
I propose that in `Promises`, we accept another function which returns a `boolean` as an argument to `catch`. It will enable us to write code like this:

```js
return somePromise
    .catch((reason) => reason instanceof ValidationError, reason => handleValidationError(reason)) // handle ValidationErrors
    .catch((reason) => reason instanceof InternalError, reason => handleInternalError(reason)) // handle InternalErrors
    .catch(reason => handleOtherErrors(reason)) // catch all others
```

If the passed function evaluates to `true`, call the actual rejection handler. If none of the catch are eligible to handle the rejection, it causes an unhandled rejection.

_______________________________________________
es-discuss mailing list
[hidden email]
https://mail.mozilla.org/listinfo/es-discuss
Reply | Threaded
Open this post in threaded view
|

Re: Proposal: Conditional `catch` in Promises

T.J. Crowder-2
For my part, if we're going to get into optional catching, I'd rather see a common approach between promise `catch` and `try`/`catch`. There have been various discussions about optional/filtered `catch` on the list ([here][1] and [here][2], probably others).

Your approach is easily implemented in userland:

```js
const cif = (predicate, handler) => e => {
    if (predicate(e)) {
        return handler(e);
    }
    throw e;
};
```

then

```js
somePromise
    .catch(cif(reason => reason instanceof ValidationError, reason => handleValidationError(reason))) // handle ValidationErrors
    .catch(cif(reason => reason instanceof InternalError, reason => handleInternalError(reason))) // handle InternalErrors
    .catch(cif(reason => handleOtherErrors(reason))); // catch all others
```


To be clear, I'm not saying that just because something can be implemented in userland, it shouldn't be considered. (Lots of things can be implemented in userland.) But again, I'd want to see a cohesive approach, and I think this probably doesn't take us in that direction.

-- T.J. Crowder


On Tue, Apr 24, 2018 at 10:35 AM, Ayush Gupta
<[hidden email]> wrote:

> I propose that in `Promises`, we accept another function which returns a
> `boolean` as an argument to `catch`. It will enable us to write code like
> this:
>
> ```js
> return somePromise
>     .catch((reason) => reason instanceof ValidationError, reason =>
> handleValidationError(reason)) // handle ValidationErrors
>     .catch((reason) => reason instanceof InternalError, reason =>
> handleInternalError(reason)) // handle InternalErrors
>     .catch(reason => handleOtherErrors(reason)) // catch all others
> ```
>
> If the passed function evaluates to `true`, call the actual rejection
> handler. If none of the catch are eligible to handle the rejection, it
> causes an unhandled rejection.
>
> _______________________________________________
> es-discuss mailing list
> [hidden email]
> https://mail.mozilla.org/listinfo/es-discuss


_______________________________________________
es-discuss mailing list
[hidden email]
https://mail.mozilla.org/listinfo/es-discuss
Reply | Threaded
Open this post in threaded view
|

Re: Re: Proposal: Conditional `catch` in Promises

Ayush Gupta
In reply to this post by Ayush Gupta
We could potentially provide the same functionality in `try/catch` by extending the signature of `catch` to

```js
try {

} catch(<expression_var>, <function_expression>) {

}
```

If `<function_expression>` evaluates to truthy, invoke the `catch` block, otherwise don't.

_______________________________________________
es-discuss mailing list
[hidden email]
https://mail.mozilla.org/listinfo/es-discuss
Reply | Threaded
Open this post in threaded view
|

Re: Re: Proposal: Conditional `catch` in Promises

Isiah Meadows-2
I'd still prefer we wait until pattern matching [1] gets addressed first, then tackling this. Error types are represented about 50 different ways in JS, with subtyping only being one (used by the standard kind of). Node appends an `err.code`, and the DOM adds a similar type, just using a common error subclass. And in some cases where errors are planned (but exceptions are more convenient), you sometimes see non-errors thrown. So there needs to be a means of catching all of them, and `if` checks get verbose and noisy in a hurry.

On Wed, Apr 25, 2018, 00:11 Ayush Gupta <[hidden email]> wrote:
We could potentially provide the same functionality in `try/catch` by extending the signature of `catch` to

```js
try {

} catch(<expression_var>, <function_expression>) {

}
```

If `<function_expression>` evaluates to truthy, invoke the `catch` block, otherwise don't.
_______________________________________________
es-discuss mailing list
[hidden email]
https://mail.mozilla.org/listinfo/es-discuss

_______________________________________________
es-discuss mailing list
[hidden email]
https://mail.mozilla.org/listinfo/es-discuss
Reply | Threaded
Open this post in threaded view
|

Re: Re: Proposal: Conditional `catch` in Promises

Michael J. Ryan
Maybe approach typescript on this one... Not sure if that supports typed errors like C# does, but would probably suit you well.

On Wed, Apr 25, 2018, 08:31 Isiah Meadows <[hidden email]> wrote:
I'd still prefer we wait until pattern matching [1] gets addressed first, then tackling this. Error types are represented about 50 different ways in JS, with subtyping only being one (used by the standard kind of). Node appends an `err.code`, and the DOM adds a similar type, just using a common error subclass. And in some cases where errors are planned (but exceptions are more convenient), you sometimes see non-errors thrown. So there needs to be a means of catching all of them, and `if` checks get verbose and noisy in a hurry.

On Wed, Apr 25, 2018, 00:11 Ayush Gupta <[hidden email]> wrote:
We could potentially provide the same functionality in `try/catch` by extending the signature of `catch` to

```js
try {

} catch(<expression_var>, <function_expression>) {

}
```

If `<function_expression>` evaluates to truthy, invoke the `catch` block, otherwise don't.
_______________________________________________
es-discuss mailing list
[hidden email]
https://mail.mozilla.org/listinfo/es-discuss
_______________________________________________
es-discuss mailing list
[hidden email]
https://mail.mozilla.org/listinfo/es-discuss

_______________________________________________
es-discuss mailing list
[hidden email]
https://mail.mozilla.org/listinfo/es-discuss
Reply | Threaded
Open this post in threaded view
|

Re: Re: Proposal: Conditional `catch` in Promises

Bob Myers
What do you mean by "approach TypeScript"? Do you mean propose this feature to the TS team? TS is not about new language features (with a few exceptions). It's about typing. They're quite careful about not forking the language.

Not sure if that supports typed errors

No, it doesn't.

Bob

On Wed, Apr 25, 2018 at 9:49 PM, Michael J. Ryan <[hidden email]> wrote:
Maybe approach typescript on this one... Not sure if that supports typed errors like C# does, but would probably suit you well.

On Wed, Apr 25, 2018, 08:31 Isiah Meadows <[hidden email]> wrote:
I'd still prefer we wait until pattern matching [1] gets addressed first, then tackling this. Error types are represented about 50 different ways in JS, with subtyping only being one (used by the standard kind of). Node appends an `err.code`, and the DOM adds a similar type, just using a common error subclass. And in some cases where errors are planned (but exceptions are more convenient), you sometimes see non-errors thrown. So there needs to be a means of catching all of them, and `if` checks get verbose and noisy in a hurry.

On Wed, Apr 25, 2018, 00:11 Ayush Gupta <[hidden email]> wrote:
We could potentially provide the same functionality in `try/catch` by extending the signature of `catch` to

```js
try {

} catch(<expression_var>, <function_expression>) {

}
```

If `<function_expression>` evaluates to truthy, invoke the `catch` block, otherwise don't.
_______________________________________________
es-discuss mailing list
[hidden email]
https://mail.mozilla.org/listinfo/es-discuss
_______________________________________________
es-discuss mailing list
[hidden email]
https://mail.mozilla.org/listinfo/es-discuss

_______________________________________________
es-discuss mailing list
[hidden email]
https://mail.mozilla.org/listinfo/es-discuss



_______________________________________________
es-discuss mailing list
[hidden email]
https://mail.mozilla.org/listinfo/es-discuss
Reply | Threaded
Open this post in threaded view
|

Re: Re: Proposal: Conditional `catch` in Promises

Ayush Gupta
It might be worth **explicitly** mentioning that it's not about types either, the benefit with using functions as the filter is that we can tackle a lot of cases. Consider this:

```js
return somePromise
    .catch((reason) => reason instanceof ValidationError, reason => handleValidationError(reason))
    .catch((reason) => reason.code === 'ENOENT', reason => handleENOENT(reason))
    .catch(reason => handleOtherErrors(reason)) // catch all others
```


On Wed, Apr 25, 2018 at 10:25 PM, Bob Myers <[hidden email]> wrote:
What do you mean by "approach TypeScript"? Do you mean propose this feature to the TS team? TS is not about new language features (with a few exceptions). It's about typing. They're quite careful about not forking the language.

Not sure if that supports typed errors

No, it doesn't.

Bob

On Wed, Apr 25, 2018 at 9:49 PM, Michael J. Ryan <[hidden email]> wrote:
Maybe approach typescript on this one... Not sure if that supports typed errors like C# does, but would probably suit you well.

On Wed, Apr 25, 2018, 08:31 Isiah Meadows <[hidden email]> wrote:
I'd still prefer we wait until pattern matching [1] gets addressed first, then tackling this. Error types are represented about 50 different ways in JS, with subtyping only being one (used by the standard kind of). Node appends an `err.code`, and the DOM adds a similar type, just using a common error subclass. And in some cases where errors are planned (but exceptions are more convenient), you sometimes see non-errors thrown. So there needs to be a means of catching all of them, and `if` checks get verbose and noisy in a hurry.

On Wed, Apr 25, 2018, 00:11 Ayush Gupta <[hidden email]> wrote:
We could potentially provide the same functionality in `try/catch` by extending the signature of `catch` to

```js
try {

} catch(<expression_var>, <function_expression>) {

}
```

If `<function_expression>` evaluates to truthy, invoke the `catch` block, otherwise don't.
_______________________________________________
es-discuss mailing list
[hidden email]
https://mail.mozilla.org/listinfo/es-discuss
_______________________________________________
es-discuss mailing list
[hidden email]
https://mail.mozilla.org/listinfo/es-discuss

_______________________________________________
es-discuss mailing list
[hidden email]
https://mail.mozilla.org/listinfo/es-discuss




_______________________________________________
es-discuss mailing list
[hidden email]
https://mail.mozilla.org/listinfo/es-discuss
Reply | Threaded
Open this post in threaded view
|

Re: Proposal: Conditional `catch` in Promises

kai zhu

On 26 Apr 2018, at 12:08 PM, Ayush Gupta <[hidden email]> wrote:

It might be worth **explicitly** mentioning that it's not about types either, the benefit with using functions as the filter is that we can tackle a lot of cases. Consider this:

```js
return somePromise
    .catch((reason) => reason instanceof ValidationError, reason => handleValidationError(reason))
    .catch((reason) => reason.code === 'ENOENT', reason => handleENOENT(reason))
    .catch(reason => handleOtherErrors(reason)) // catch all others
```


can someone give a sane javascript styleguide on when to use the above and when to use this code below?  otherwise, we’re simply adding to the industry-painpoint of the language having too many cross-cutting design-patterns, leading to hard-to-maintain web-projects with inconsistent code across its components.

```js
return somePromise
    .catch((function (reason) {
        if (reason instanceof ValidationError) {
            return handleValidationError(reason);
        }
        if (reason.code === 'ENOENT') {
            return handleENOENT(reason);
        }
        return handleOtherErrors(reason)) // catch all others
    });
```


On Wed, Apr 25, 2018 at 10:25 PM, Bob Myers <[hidden email]> wrote:
What do you mean by "approach TypeScript"? Do you mean propose this feature to the TS team? TS is not about new language features (with a few exceptions). It's about typing. They're quite careful about not forking the language.

Not sure if that supports typed errors

No, it doesn't.

Bob

On Wed, Apr 25, 2018 at 9:49 PM, Michael J. Ryan <[hidden email]> wrote:
Maybe approach typescript on this one... Not sure if that supports typed errors like C# does, but would probably suit you well.

On Wed, Apr 25, 2018, 08:31 Isiah Meadows <[hidden email]> wrote:
I'd still prefer we wait until pattern matching [1] gets addressed first, then tackling this. Error types are represented about 50 different ways in JS, with subtyping only being one (used by the standard kind of). Node appends an `err.code`, and the DOM adds a similar type, just using a common error subclass. And in some cases where errors are planned (but exceptions are more convenient), you sometimes see non-errors thrown. So there needs to be a means of catching all of them, and `if` checks get verbose and noisy in a hurry.

On Wed, Apr 25, 2018, 00:11 Ayush Gupta <[hidden email]> wrote:
We could potentially provide the same functionality in `try/catch` by extending the signature of `catch` to

```js
try {

} catch(<expression_var>, <function_expression>) {

}
```

If `<function_expression>` evaluates to truthy, invoke the `catch` block, otherwise don't.
_______________________________________________
es-discuss mailing list
[hidden email]
https://mail.mozilla.org/listinfo/es-discuss
_______________________________________________
es-discuss mailing list
[hidden email]
https://mail.mozilla.org/listinfo/es-discuss

_______________________________________________
es-discuss mailing list
[hidden email]
https://mail.mozilla.org/listinfo/es-discuss



_______________________________________________
es-discuss mailing list
[hidden email]
https://mail.mozilla.org/listinfo/es-discuss


_______________________________________________
es-discuss mailing list
[hidden email]
https://mail.mozilla.org/listinfo/es-discuss
Reply | Threaded
Open this post in threaded view
|

Re: Proposal: Conditional `catch` in Promises

Isiah Meadows-2
I agree this isn't ideal (it's a design hack that wasn't very well
thought through on the part of Bluebird IMHO), but not on your
justification (which comes across as borderline off-topic). Most
complex exception handling with promises are effectively handled using
async/await, but I agree the simple stuff shouldn't be made more
complex without justification. If we're going to do type guards like
that, we have to run it in the same tick as the subsequent block, then
for efficiency purposes, what's the point of the guard callback? For a
change this substantial, I'm not convinced it is broadly useful enough
(unlike exception handling with guarded `catch` blocks), especially
with async functions increasingly starting to replace most
promise-heavy code.

-----

Isiah Meadows
[hidden email]

Looking for web consulting? Or a new website?
Send me an email and we can get started.
www.isiahmeadows.com


On Thu, Apr 26, 2018 at 2:11 AM, kai zhu <[hidden email]> wrote:

>
> On 26 Apr 2018, at 12:08 PM, Ayush Gupta <[hidden email]> wrote:
>
> It might be worth **explicitly** mentioning that it's not about types
> either, the benefit with using functions as the filter is that we can tackle
> a lot of cases. Consider this:
>
> ```js
> return somePromise
>     .catch((reason) => reason instanceof ValidationError, reason =>
> handleValidationError(reason))
>     .catch((reason) => reason.code === 'ENOENT', reason =>
> handleENOENT(reason))
>     .catch(reason => handleOtherErrors(reason)) // catch all others
> ```
>
>
> can someone give a sane javascript styleguide on when to use the above and
> when to use this code below?  otherwise, we’re simply adding to the
> industry-painpoint of the language having too many cross-cutting
> design-patterns, leading to hard-to-maintain web-projects with inconsistent
> code across its components.
>
> ```js
> return somePromise
>     .catch((function (reason) {
>         if (reason instanceof ValidationError) {
>             return handleValidationError(reason);
>         }
>         if (reason.code === 'ENOENT') {
>             return handleENOENT(reason);
>         }
>         return handleOtherErrors(reason)) // catch all others
>     });
> ```
>
> kai zhu
> [hidden email]
>
>
> On Wed, Apr 25, 2018 at 10:25 PM, Bob Myers <[hidden email]> wrote:
>>
>> What do you mean by "approach TypeScript"? Do you mean propose this
>> feature to the TS team? TS is not about new language features (with a few
>> exceptions). It's about typing. They're quite careful about not forking the
>> language.
>>
>> >  Not sure if that supports typed errors
>>
>> No, it doesn't.
>>
>> Bob
>>
>> On Wed, Apr 25, 2018 at 9:49 PM, Michael J. Ryan <[hidden email]>
>> wrote:
>>>
>>> Maybe approach typescript on this one... Not sure if that supports typed
>>> errors like C# does, but would probably suit you well.
>>>
>>> On Wed, Apr 25, 2018, 08:31 Isiah Meadows <[hidden email]> wrote:
>>>>
>>>> I'd still prefer we wait until pattern matching [1] gets addressed
>>>> first, then tackling this. Error types are represented about 50 different
>>>> ways in JS, with subtyping only being one (used by the standard kind of).
>>>> Node appends an `err.code`, and the DOM adds a similar type, just using a
>>>> common error subclass. And in some cases where errors are planned (but
>>>> exceptions are more convenient), you sometimes see non-errors thrown. So
>>>> there needs to be a means of catching all of them, and `if` checks get
>>>> verbose and noisy in a hurry.
>>>>
>>>> On Wed, Apr 25, 2018, 00:11 Ayush Gupta <[hidden email]> wrote:
>>>>>
>>>>> We could potentially provide the same functionality in `try/catch` by
>>>>> extending the signature of `catch` to
>>>>>
>>>>> ```js
>>>>> try {
>>>>>
>>>>> } catch(<expression_var>, <function_expression>) {
>>>>>
>>>>> }
>>>>> ```
>>>>>
>>>>> If `<function_expression>` evaluates to truthy, invoke the `catch`
>>>>> block, otherwise don't.
>>>>> _______________________________________________
>>>>> es-discuss mailing list
>>>>> [hidden email]
>>>>> https://mail.mozilla.org/listinfo/es-discuss
>>>>
>>>> _______________________________________________
>>>> es-discuss mailing list
>>>> [hidden email]
>>>> https://mail.mozilla.org/listinfo/es-discuss
>>>
>>>
>>> _______________________________________________
>>> es-discuss mailing list
>>> [hidden email]
>>> https://mail.mozilla.org/listinfo/es-discuss
>>>
>>
>
> _______________________________________________
> es-discuss mailing list
> [hidden email]
> https://mail.mozilla.org/listinfo/es-discuss
>
>
>
> _______________________________________________
> es-discuss mailing list
> [hidden email]
> https://mail.mozilla.org/listinfo/es-discuss
>
_______________________________________________
es-discuss mailing list
[hidden email]
https://mail.mozilla.org/listinfo/es-discuss