How come resolving a settled Promise doesn't throw?

Andrea Giammarchi andrea.giammarchi at gmail.com
Wed Mar 1 10:01:38 UTC 2017


Throwing on already resolved/rejected will break the Web 'cause the
following example pattern is quite common.

```js
class Lie extends Promise {
  constructor(fn) {
    let _resolve, _reject;
    super((resolve, reject) => fn(
        _resolve = resolve,
        _reject = reject
    ));
    this._resolve = _resolve;
    this._reject = _reject;
  }
  reject(error) {
    this. _reject(error);
    return this;
  }
  resolve(how) {
    this._resolve(how);
    return this;
  }
  cancel(...reason) {
    this._reject(...reason);
    return this;
  }
}

// resolve in 5 seconds with 123
const p = new Lie((res, rej) => setTimeout(res, 5000, 'timeout'));

// however, something else could happen before / or after
setTimeout(() => p.resolve('hello there').then(console.log), 1000);
```

As summary, after years without throwing, I don't see why it should now.

Regards



On Tue, Feb 28, 2017 at 9:36 PM, Jordan Harband <ljharb at gmail.com> wrote:

> Although now that I think about it, it wouldn't have to care about the
> promise state, `resolve` and `reject` could just throw if they're invoked
> more than once.
>
> On Tue, Feb 28, 2017 at 1:35 PM, Jordan Harband <ljharb at gmail.com> wrote:
>
>> That seems like it would allow synchronous observation of Promise state -
>> consider:
>>
>> ```js
>>
>> function isResolved(promise) {
>>   try {
>>     new Promise((resolve) => {
>>       resolve(promise);
>>       resolve();
>>     });
>>   } catch (e) {
>>     return true;
>>   }
>>   return false;
>> }
>>
>> ```
>>
>> On Tue, Feb 28, 2017 at 12:58 PM, Isiah Meadows <isiahmeadows at gmail.com>
>> wrote:
>>
>>> Also, making promise resolution idempotent makes dealing with things way
>>> easier. Similarly, most deferred libraries ensure their resolution is
>>> idempotent.
>>>
>>> On Tue, Feb 28, 2017, 13:20 Tab Atkins Jr. <jackalmage at gmail.com> wrote:
>>>
>>>> On Tue, Feb 28, 2017 at 10:12 AM, /#!/JoePea <joe at trusktr.io> wrote:
>>>> > f.e.
>>>> >
>>>> > ```js
>>>> > let resolve
>>>> > let p = new Promise(r => resolve = r)
>>>> >
>>>> > resolve(5) //  resolves the promise.
>>>> > resolve(4) // noop (in Chrome), but why not throw an error?
>>>> > ```
>>>> >
>>>> > I only tested in Chrome, and I'm assuming it follows spec, but I
>>>> could be
>>>> > wrong.
>>>> >
>>>> > I'm asking because it seems that throwing an error will prevent shots
>>>> in the
>>>> > foot, so that code doesn't assume that resolving on an already
>>>> resolved
>>>> > Promise worked, although it didn't. It seems like it can lead to
>>>> unexpected
>>>> > failures.
>>>>
>>>> That's correct behavior, yes.  In general, it's because the internal
>>>> state of a promise is meant to be unobservable unless you're
>>>> specifically listening to it.
>>>>
>>>> ~TJ
>>>> _______________________________________________
>>>> es-discuss mailing list
>>>> es-discuss at mozilla.org
>>>> https://mail.mozilla.org/listinfo/es-discuss
>>>>
>>>
>>> _______________________________________________
>>> es-discuss mailing list
>>> es-discuss at mozilla.org
>>> https://mail.mozilla.org/listinfo/es-discuss
>>>
>>>
>>
>
> _______________________________________________
> es-discuss mailing list
> es-discuss at mozilla.org
> https://mail.mozilla.org/listinfo/es-discuss
>
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://mail.mozilla.org/pipermail/es-discuss/attachments/20170301/410ef60d/attachment.html>


More information about the es-discuss mailing list