JavaScript获取promise的状态

JavaScript获取promise的状态,第1张

获取promise的状态

面试被问到这个问题,记录一下。

promise的状态

一个 Promise 必然处于以下几种状态之一:

待定(pending): 初始状态,既没有被兑现,也没有被拒绝。已兑现(fulfilled): 意味着 *** 作成功完成。已拒绝(rejected): 意味着 *** 作失败。 利用 Promise.race 实现

从 stackoverflow 这篇 回答 找到一个答案,借助了 Promise.race

const PROMISE_STATE = {
  PENDING: 'pending',
  FULFILLED: 'fulfilled',
  REJECTED: 'rejected'
}

function decidePromiseState(promise) {
  const t = {};
  return Promise.race([promise, t])
  .then(v => (v === t) ? PROMISE_STATE.PENDING : PROMISE_STATE.FULFILLED)
  .catch(() => PROMISE_STATE.REJECTED)
}

let a = Promise.resolve();
let b = Promise.reject();
let c = new Promise(() => {});

decidePromiseState(a).then(state => console.log(state)); // fulfilled
decidePromiseState(b).then(state => console.log(state)); // rejected
decidePromiseState(c).then(state => console.log(state)); // pending

验证通过:


有个值得注意的细节是,Promise.race([promise, t]) 必须把 promise 放在 t 前面,倒过来的话输出的状态都是pending。因为测试中a、b的状态都是确定了的,t是常量对象,也是确定的,所以 race 先跑出结果的是先入队的 t

验证代码如下:

const PROMISE_STATE = {
  PENDING: 'pending',
  FULFILLED: 'fulfilled',
  REJECTED: 'rejected'
}

function decidePromiseState(promise) {
  const t = {name: 'foo'};
  return Promise.race([t, promise])
  .then(v => {
    console.log('resolved:', v)
    return (v === t) ? PROMISE_STATE.PENDING : PROMISE_STATE.FULFILLED
  })
  .catch(() => PROMISE_STATE.REJECTED)
}

let a = Promise.resolve(1);
let b = Promise.reject(2);
let c = new Promise(() => {});

decidePromiseState(a).then(state => console.log(state)); // fulfilled
decidePromiseState(b).then(state => console.log(state)); // rejected
decidePromiseState(c).then(state => console.log(state)); // pending

利用事件循环机制实现

事件循环详细介绍参考文章:https://zhuanlan.zhihu.com/p/33058983
浏览器环境JavaScript的异步任务分为 宏任务 和 微任务
宏任务:setInterval() setTimeout()
微任务:new Promise() new MutaionObserver()

当前执行栈执行完毕时会立刻先处理所有微任务队列中的事件,然后再去宏任务队列中取出一个事件。同一次事件循环中,微任务永远在宏任务之前执行。

看个简单的例子

setTimeout(function () {
    console.log(1);
});

new Promise(function(resolve,reject){
    console.log(2)
    resolve(3)
}).then(function(val){
    console.log(val);
})

// 输出
2
3
1

那么答案就呼之欲出了!

const PROMISE_STATE = {
  PENDING: 'pending',
  FULFILLED: 'fulfilled',
  REJECTED: 'rejected'
}

function decidePromiseState(promise) {
  return new Promise((resolve, reject) => {
    setTimeout(() => {
      resolve(PROMISE_STATE.PENDING);
    }, 0);
    promise.then(() => {
      resolve(PROMISE_STATE.FULFILLED);
    }).catch(() => {
      resolve(PROMISE_STATE.REJECTED);
    });
  })

}

let a = Promise.resolve();
let b = Promise.reject();
let c = new Promise(() => {});

decidePromiseState(a).then(state => console.log(state)); // fulfilled
decidePromiseState(b).then(state => console.log(state)); // rejected
decidePromiseState(c).then(state => console.log(state)); // pending

验证成功

来单独看看 nodejs 环境

在这篇文章找到一个依赖V8内部实现的检测方法。

实验代码(下述代码在以下node版本测试过:v14.17.0 v16.15.0 v18.2.0

let p1 = Promise.resolve();
let p2 = Promise.reject();
let p3 = Promise.resolve(1024);
let p4 = Promise.reject('出错了');

console.log(p1);
console.log(p2);
console.log(p3);
console.log(p4);

我们用 console.log 是可以看到 promise 状态的。忽略日志中的警告,那个是因为没有对 promise.catch 处理

再来看下处于 pending 的 promise 输出什么

let p = new Promise((resolve, reject) => {
    setTimeout(() => {
        resolve(1024);
        // reject('出错了')
    }, 3000);
});

setInterval(() => {
  console.log(p);
},1000);

那么有什么办法可以拿到这个输出的字符串呢?答案是 util.inspect

const util = require('util')

let p = new Promise((resolve, reject) => {
    setTimeout(() => {
              resolve(1024);
              // reject('出错了')
    }, 3000);
});

p.catch(err => {
  console.log('rejected', err)
})

console.log(typeof util.inspect(p));  // string

setInterval(() => {
  console.log(util.inspect(p));
},1000);



现在可以写出判断函数

const PROMISE_STATE = {
  PENDING: 'pending',
  FULFILLED: 'fulfilled',
  REJECTED: 'rejected'
}

function decidePromiseState(promise) {
  const inspectStr = util.inspect(promise);
  if (inspectStr.includes(PROMISE_STATE.PENDING)) {
    return PROMISE_STATE.PENDING;
  } else if (inspectStr.includes(PROMISE_STATE.REJECTED)) {
    return PROMISE_STATE.REJECTED;
  } else {
    return PROMISE_STATE.FULFILLED;
  }
}

测试结果正确。

欢迎分享,转载请注明来源:内存溢出

原文地址: http://outofmemory.cn/web/1321211.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2022-06-12
下一篇 2022-06-12

发表评论

登录后才能评论

评论列表(0条)

保存