首页 > 解决方案 > 如何避免此并发计时器的显式 Promise 构造反模式应在承诺完成时重置?

问题描述

我写了一个非常简单的脚本:

{
   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...
    },
 }

它为搜索字段触发等待微调器。

有人给我写信说:

您的代码具有 Explicit Promise 构造反模式!您应该改用链接和承诺组合...此外,返回承诺但不等待任何内容的函数不必是异步的

我修改了这个工作代码。但我得到的只是错误错误!

有人可以帮我解决这个问题,或者至少让我走上正轨。

我不太擅长 javascript,但我有兴趣更好地编写它。

标签: javascriptpromiseasync-awaitsettimeout

解决方案


请参阅什么是显式承诺构造反模式以及如何避免它?详情。new Promise一般来说,当你已经有一个承诺时,你(大部分)不需要。您可以只重用现有的(如有必要,将其链接起来)。

您的代码可以简化。

  • 去掉不必要的new Promise
  • 重用并返回现有的 Promise
  • 删除代码重复并Promise#finally改用
{
  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...
  },
}

你也可以摆脱loadingStarted它。你有两个状态变量是有原因的吗?loadingStarted无论如何,您永远不会重置。

{
  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...
  },
}

推荐阅读