如何检查Promise是否处于待定状态

67

我有这样的情况,想知道一个promise的状态是什么。下面的start函数只有在它不再运行(Promise没有处于pending状态)时才调用someTest函数。 start函数可以被多次调用,但如果在测试仍在运行时调用它,它不会等待并且仅返回false

class RunTest {
    start() {
         retVal = false;

         if (!this.promise) {
             this.promise = this.someTest();
             retVal = true;                
         }

         if ( /* if promise is resolved/rejected or not pending */ ) {
             this.promise = this.someTest();
             retVal = true;
         }

         return retVal;
    }

    someTest() {
        return new Promise((resolve, reject) => {
            // some tests go inhere
        });
    }
}

我找不到一种简单的方法来检查一个 Promise 的状态。类似 this.promise.isPending 这样的东西会很好 :) 感谢任何帮助!

我无法找到一种简单的方法来检查 Promise 的状态。类似于 this.promise.isPending 这样的东西将会很棒 :) 感谢任何帮助!


1
什么是用例?我认为原生的 Promises 不支持这个,这是一个奇怪的想法,但 Blubird 可以。http://bluebirdjs.com/docs/api/ispending.html - elclanrs
在我的情况下,它是一个setInterval一直调用异步函数。而且那个东西每次只应该运行一次。当然,我可以在this上设置一个变量,比如this.isBusy = true。但在我看来,这听起来像是不知道承诺状态的权宜之计。 - Jeanluca Scaljeri
Mozilla的页面确实很棒,但是关于如何检查Promise的状态并没有任何内容。如果我错过了,请告诉我! - Jeanluca Scaljeri
25
检查一个Promise是否处于等待状态似乎并不“奇怪”,它似乎非常基础。 - jchook
4
我想知道将此标记为重复的人是否意识到,这是一个纯粹的Javascript问题,而重复的则是一个Node.js问题。其中一个标记它为重复的投票甚至提到了一个在此情况下不适用的Node库。可惜。 - netskink
显示剩余2条评论
2个回答

35

您可以附加一个then处理程序,该处理程序在承诺(或者如果您更喜欢,则是RunTest实例)上设置一个done标志,并进行测试:

     if (!this.promise) {
         this.promise = this.someTest();
         this.promise.finally(() => { this.promise.done = true; });
         retVal = true;                
     }

     if ( this.promise.done ) {
         this.promise = this.someTest();
         this.promise.finally(() => { this.promise.done = true; });
         retVal = true;
     }

finally() 处理程序确保无论 Promise 的结果如何,都设置了 done 标志。

您可能想将其包装在函数中,以保持代码 DRY。


1
我猜只需要执行 this.promise = null 会更容易。 - Bergi
1
一个"空的" catch 参数是无效的。你仍然需要显式地传递一个空函数,否则它就毫无意义。 - Bergi
1
@Bergi - 关于空catch的观点很好,现在进行更正...关于this.promise = null,对于这个特定的情况是可以的,但在一般情况下不够健壮。例如,如果promise暴露在函数外部,那么在promise上有可用的属性会更好。 - Amit
当然,但通常没有人期望在 Promise 上使用这样的属性,因此没有必要公开它。在所有情况下,您认为需要确定 Promise 的状态时,实际上您需要检查回调函数是否已经被调用。 - Bergi
10
顺便说一下,考虑使用.finally()替换.catch(() => {}).then() - Thomas Urban

2
class RunTest {
   constructor() {
    this.isRunning = false;
   }
   start() {
      console.log('isrunning', this.isRunning);
      var retVal = false;
      if(!this.isRunning) {
        this.promise = this.someTest();
        this.promise.catch().then(() => { this.isRunning = false; });
        retVal = true;                
      }
      return retVal;
    }
    someTest() {
        this.isRunning = true;
        return new Promise((resolve, reject) => {
          setTimeout(function() {
             //some tests go inhere
             resolve();
           }, 1000);
        });
    }
};

var x = new RunTest();

x.start(); //logs false
x.start(); //logs true

setTimeout(function() {
    //wait for a bit
  x.start(); //logs false
}, 2000);

1
then() 后返回 Promise 的缺点是,无法将已解决的值传递给下一个处理程序。此外,如果测试抛出异常,则此方法不起作用(请参阅我的答案)。 - Amit
1
then回调函数已经失去了方法的上下文 - Bergi
https://jsfiddle.net/tchalvakspam/wszyqj3t/3/ - Kzqai
@Amit 更改为 .then(resp => { this.isRunning = false; return resp; }) 可以轻松解决这个问题;然而,用 .finally() 替换 .catch().then() 是一个更好的解决方案。 - Daniel

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接