我有一个纯JavaScript承诺(内置实现或poly-fill):

var promise = new promise(函数(解析,拒绝){/*…* /});

从规范来看,Promise可以是:

" settle "和" resolved " “解决”和“拒绝” “等待”

我有一个用例,我希望同步审问承诺并确定:

承诺达成了吗? 如果是,承诺解决了吗?

我知道我可以使用#then()来安排在Promise改变状态后异步执行的工作。我不是在问你该怎么做。

这个问题是关于Promise状态的同步询问。我怎样才能做到这一点呢?


当前回答

使用惯用的原型,等待@jib的答案的使用。

Object.defineProperty(Promise.prototype, "state", {
    get: function(){
        const o = {};
        return Promise.race([this, o]).then(
            v => v === o ? "pending" : "resolved",
            () => "rejected");
    }
});

// usage: console.log(await <Your Promise>.state);
(async () => {
    console.log(await Promise.resolve(2).state);  // "resolved"
    console.log(await Promise.reject(0).state);   // "rejected"
    console.log(await new Promise(()=>{}).state); // "pending"
})();

注意,这个异步函数像同步函数一样“几乎”立即执行(或者实际上可能立即执行)。

其他回答

从Node.js版本8开始,您现在可以使用智能检查包来同步检查本机承诺(没有任何危险的黑客)。

我为此做了一个包裹。与这里的大多数其他答案不同,它不会接受未经处理的拒绝。

npm install p-state
import timers from 'timers/promises';
import {promiseStateSync} from 'p-state';

const timeoutPromise = timers.setTimeout(100);

console.log(promiseStateSync(timeoutPromise));
//=> 'pending'

await timeoutPromise;

console.log(promiseStateSync(timeoutPromise));
//=> 'fulfilled'

如果你正在使用ES7实验版,你可以使用async轻松地包装你想要收听的承诺。

async function getClient() {
  let client, resolved = false;
  try {
    client = await new Promise((resolve, reject) => {
      let client = new Client();

      let timer = setTimeout(() => {
         reject(new Error(`timeout`, 1000));
         client.close();
      });

      client.on('ready', () => {
        if(!resolved) {
          clearTimeout(timer);
          resolve(client);
        }
      });

      client.on('error', (error) => {
        if(!resolved) {
          clearTimeout(timer);
          reject(error);
        }
      });

      client.on('close', (hadError) => {
        if(!resolved && !hadError) {
          clearTimeout(timer);
          reject(new Error("close"));
        }
      });
    });

    resolved = true;
  } catch(error) {
    resolved = true;
    throw error;
  }
  return client;
}

老问题有很多答案,但似乎没有一个建议我认为是最简单的解决方案:在承诺解决/拒绝上设置bool指示器。

类Promise2 { 构造函数(args) { let promise = new promise(…args); promise.then(() => promise。_resolved_ = true); promise.catch(() => promise。_rejected_ = true); 返回的诺言; } } let p = new promise (r => setTimeout(r, 3000)); setInterval(() => { Console.log('正在同步检查p是否已解析?”,p._resolved_); }, 1000);

在节点中,写入未记录的内部进程。

> process.binding('util').getPromiseDetails(Promise.resolve({data: [1,2,3]}));
[ 1, { data: [ 1, 2, 3 ] } ]

> process.binding('util').getPromiseDetails(Promise.reject(new Error('no')));
[ 2, Error: no ]

> process.binding('util').getPromiseDetails(new Promise((resolve) => {}));
[ 0, <1 empty item> ]