向Promise.allSettled传入非Promise值(false)的代码原理及安全性疑问
向Promise.allSettled传入非Promise值(false)的代码原理及安全性疑问
嗨,这个问题问得很到位!我来帮你拆解这段代码的运行原理,以及这种写法的安全性~
先澄清Promise.allSettled的实际行为
MDN里说它“期望一个Promise数组”其实是一种简化表述,实际上它接受的是任意可迭代对象(比如数组),里面的元素可以是任何值,不一定必须是Promise。规范里明确规定,Promise.allSettled会自动把每个元素通过Promise.resolve()包装成Promise对象——哪怕你传的是false、数字、字符串这类原始值,都会被转换成一个resolved状态的Promise,对应的值就是你传入的原始值。
分析你的代码逻辑
来看你这段代码:
let log = async x => console.log(x) let flag = false let main = async () => { await Promise.allSettled([ flag && log(0), log(1) ]) } main()
- 当
flag为false时,flag && log(0)的逻辑结果就是false(因为逻辑与运算中,第一个值为false时会直接返回它,不会执行后面的log(0)),这个false会被Promise.allSettled包装成Promise.resolve(false),这个Promise会以resolved状态完成,不会产生任何输出。 - 第二个元素
log(1)是一个async函数调用,本身就返回Promise,执行后会打印1,随后这个Promise进入resolved状态。 Promise.allSettled会等待所有包装后的Promise都进入settled状态(不管成功还是失败),所以你的代码会正常执行,最终输出1。
这种写法的安全性
可以放心,这种写法是完全安全的,完全符合ECMAScript的规范要求。Promise.allSettled的设计就是兼容非Promise值的,内部的自动包装逻辑是标准化的,不会出现未定义的行为。
不过有个小细节要留意:如果你这里的flag && log(0)是想在flag为true时才执行异步操作log(0),那这种写法是完全符合预期的——因为flag为false时,log(0)根本不会被调用,只会返回false,不会触发不必要的异步任务。
备注:内容来源于stack exchange,提问作者kofifus
相关产品推荐
相关产品推荐

