面试被问到这个问题,记录一下。
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
验证成功
在这篇文章找到一个依赖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;
}
}
测试结果正确。
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)