How to avoid the explicit Promise construction antipattern for this concurrent timer that should reset when the promise completes?

倖福魔咒の 提交于 2021-01-28 18:20:29

问题


I have written a pretty simply script:

{
   waiting: false,

   async handleWaiting(promise, timeout) {
       return new Promise((res, rej) => {
           let loadingStarted = false;

           const timeoutInstance = setTimeout(() => {
               loadingStarted = true;
               this.waiting = true;
           }, timeout);

           const onFinished = () => {
               if (loadingStarted) {
                   this.waiting = false;
               }
               clearTimeout(timeoutInstance);
           }

           promise
               .then((result) => {
                   onFinished();
                   res(result);
               })
               .catch((ex) => {
                   onFinished();
                   rej(ex);
               });
       });
    },

    async searchForTerm(term) {
       this.results = await this.handleWaiting(this.$wire.query(term), 500);
       // do something with the results...
    },
 }

It tiggers the waiting spinner for a search field.

Someone wrote me, that:

Your code has the Explicit Promise construction antipattern! You should use chaining and promise composition instead... Also, a function that returns a promise, but doesn't await anything don't have to be async

I tinkered around with this working code. But I got just error over error!

Can someone help me with this, or at least put me on the right track.

I am not that good with javascript but I am interested in writing it better.


回答1:


See What is the explicit promise construction antipattern and how do I avoid it? for details. Generally speaking, you (mostly) do not need new Promise when you already have a promise. You can just reuse the existing one (and chain it if necessary).

Your code can be simplied.

  • Remove the unnecessary new Promise
  • Reuse and return the existing promise
  • Remove code duplication and use Promise#finally instead
{
  waiting: false,

  handleWaiting(promise, timeout) {
    let loadingStarted = false;

    const timeoutInstance = setTimeout(() => {
      loadingStarted = true;
      this.waiting = true;
    }, timeout);

    return promise.finally(() => {
      if (loadingStarted) {
        this.waiting = false;
      }
      clearTimeout(timeoutInstance);
    });
  },

  async searchForTerm(term) {
    this.results = await this.handleWaiting(this.$wire.query(term), 500);
    // do something with the results...
  },
}

And you can probably get rid of loadingStarted as well. Is there a reason why you have two state variables for that? You never reset loadingStarted anyway.

{
  waiting: false,

  handleWaiting(promise, timeout) {
    const timeoutInstance = setTimeout(() => {
      this.waiting = true;
    }, timeout);
    return promise.finally(() => {
      this.waiting = false;
      clearTimeout(timeoutInstance);
    });
  },

  async searchForTerm(term) {
    this.results = await this.handleWaiting(this.$wire.query(term), 500);
    // do something with the results...
  },
}


来源:https://stackoverflow.com/questions/65264570/how-to-avoid-the-explicit-promise-construction-antipattern-for-this-concurrent-t

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!