Promise.finally not really final

Augusto Moura augusto.borgesm at gmail.com
Fri Sep 7 23:18:30 UTC 2018


Why would you destroy a node and `.then()` pause it? It doesn't make
sense even in plain English. If the contract of the method (expected
behavior) is to destroy the internal node, using it after is a error.
You can easily reimplement your use case reversing the logic:

```` js
setTimeout(() => {
  demo.node.pause();
  demo.destroy();
}, 3000);
````

Another solution is to implement a `beforeDestroy` event emitter and
listen to it, this way is certain that the code will be executed
always before the node is gone and after any async destroy logic:

```` js
class Demo {
  constructor(el) {
    this.beforeDestroy = new EventEmitter();
    // Using the @angular/core EventEmitter because is more "close to English"
    this.node = el;
  }
  destroy() {
    return new Promise(resolve => resolve())
      .then(() => this.beforeDestroy.emit())
      .finally(() => {
        this.node = null;
      });
  }
}

const demo = new Demo(document.querySelector('video'));

demo.beforeDestroy.subscribe(() => {
  demo.node.pause();
});

setTimeout(() => {
  demo.destroy();
}, 3000);
````

Anyway, the `then`, `catch` and `finally` methods mimic the serial
try/catch/finally, simply doesn't make sense finally statements
protecting code beyond it's try block definition, and chaining new
`.then`s _are_ beyond the promise definition. Also, async functions
already has finally blocks implementations in the same way as the
current `.finally` method spec, implementing a different behaviour
would be unnecessarily confusing.
Em sex, 7 de set de 2018 às 16:16, Jon Ronnenberg
<jon.ronnenberg at gmail.com> escreveu:
>
> I know I am late to the game and that Promise.prototype.finally is already in stage 4 but(!).
>
> It's just not very useful to have a final function when it's not the final function to run. If it's suppose to be for cleanup, then the current implementation is seriously lacking usefulness.
>
> Consider the following example:
>
> <audio
>   class="i-am-the-element"
>   autoplay="autoplay"
>   controls="controls">
>     <source type="audio/mp3" src="http:\/\/play.dogmazic.net\/play\/index.php?type=song&oid=22951&uid=-1&name=Black%20poetry%20-%20Aime-.mp3">
> </audio>
> <script>
>   class Demo {
>     constructor (element) {
>       this.node = element
>     }
>     destroy () {
>       return new Promise(resolve => {
>         // do something or nothing
>         resolve()
>       }).finally(() => {
>         // schedule for DOM removal
>         this.node = null
>       })
>     }
>   }
>
>   const demo = new Demo(document.querySelector('.i-am-the-element'))
>
>   setTimeout(() => {
>     demo.destroy().then(() => {
>    // will throw an error because finally was run before
>       demo.node.pause()
>     }).catch(console.error)
>   }, 3000)
> </script>
>
> One grand idea about promises is to delegate and compose asynchronous functions, but the current implementation can not be used to for code delegation.
>
> From the top of my head the only way to have consumer code,  tap into an execution process is to use callbacks which is what Promises were suppose to help alleviate.
>
> <audio
>   class="i-am-the-element"
>   autoplay="autoplay"
>   controls="controls">
>     <source type="audio/mp3" src="http:\/\/play.dogmazic.net\/play\/index.php?type=song&oid=22951&uid=-1&name=Black%20poetry%20-%20Aime-.mp3">
> </audio>
> <script>
>   class Demo {
>     constructor (element) {
>       this.node = element
>     }
>     destroy (callback) {
>       // do something or nothing
>       try {
>         callback()
>       } finally {
>         // schedule for DOM removal
>         this.node = null
>       }
>     }
>   }
>
>   const demo = new Demo(document.querySelector('.i-am-the-element'))
>
>   setTimeout(() => {
>     demo.destroy(() => {
>       demo.node.pause()
>     })
>   }, 3000)
> </script>
>
> If at all possible, please amend to the spec before it's too late! ... or just drop it.
>
> My current use-case is that I work with PSPDFKit and can not get DOM access but rather schedule removal of DOM nodes via their API, but I can pause audio/video - just not using Promise.prototype.finally as it is currently envisioned.
>
> Regards, Jon
>
> PS. Tested in Firefox 63.0b3 and Safari 11.1.2
> Here is a polyfill if you need: https://cdn.polyfill.io/v2/polyfill.minify.js?features=Promise.prototype.finally&flags=gated
>
> _______________________________________________
> es-discuss mailing list
> es-discuss at mozilla.org
> https://mail.mozilla.org/listinfo/es-discuss


More information about the es-discuss mailing list