看下面代码,为什么使用“错误的处理”那种情况。明明所有hasStock很快执行完毕并且返回了结果,但是会在判断没货之间,每个判断之间会卡几秒,不是已经有结果了吗。。。
GPT4 说“错误的处理”应该是秒出结果的,它也没搞明白
// 需要订购的产品链接
const productList = [
" xxx",
" xxx",
" xxx"
]

// 是否有货
const hasStock = async (url: string): Promise => {
const resp = await mAxios.get(url)
return resp.data.trim() !== ""
}

// 开始订购
const startOrder = async () => {
const promises = productList.map(u => ({tag: u, promise: hasStock(u)}))

// 根据是否有货判断购买
// 正确的处理
const results = await Promise.allSettled(promises.map(p => p.promise))
// 错误的处理
// const results = await Promise.allSettled(promises)

for (const [i, result] of results.entries()) {
// ...

// 是否有货,有就订购
if (!result.value) {
console.log("无货", promises[i].tag)
continue
}
}

这个 promises 并不是 Promise 包裹的对象,秒出的结果的状态也是只是 pending

Promise.allSettled(p) 函数的参数 p 类型是 Promise[], 而你代码里的 promises 并不是 Promise[], 而是个 Object[],而该 Object 的 prototype.promise 才是 Promise , 所以要先 map 成 p.promise 才能传给 Promise.allSettled() developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise/allSettled> The Promise.allSettled() static method takes an iterable of promises as input and returns a single Promise. This returned promise fulfills when all of the input's promises settle (including when an empty iterable is passed), with an array of objects that describe the outcome of each promise.

op 问的都不是这个问题,人家都写明是错误的处理了

传错参数了有啥好纠结为啥这结果的吗?放其他语言里编译都跑不过的,也就 js 可以这么瞎搞。你给入参是个数字的函数传个字符串然后来问算出来为啥是这结果,有啥意义?

首先 gpt 的回复是对的,确实应该是秒出结果的,而且都是 fulfilled至于为什么是 fulfilled ,是因为你传给 Promise 执行的是非 Promise ,是一个{ tag, promise }对象,而 Promise 执行非 Promise 时,永远都是 fulfilled ,并且返回值就是传进去的值至于为什么卡顿,问题并不在循环判断有没有货里面,而是 hasStock 这个方法,因为你进行了 await ,所以下面这行代码其实会卡住的const promises = productList.map(u => ({tag: u, promise: hasStock(u)}))你把 hasStock 方法改成这样,你就会发现秒出结果了const hasStock = async (url: string): Promise<boolean> => { return mAxios.get(url).then(resp => { return resp.data.trim() !== "" }, error => false);}

这个 hasStock 和楼主的有什么区别吗

问题出在 promises 数组中的每个元素应该包含 promise 属性的 Promise 对象,而不是一个对象。

传给 allSettled 时 promises 不是已经 map 过了吗

楼主问的是 错误的处理 那行

#6 他的进行了 await

很遗憾,替换网络请求为 sleep 之后无法复现问题const sleep = (ms: number) => new Promise(resolve => setTimeout(resolve, ms))// 是否有货const hasStock = async (url: string): Promise => { await sleep(1000) return true}

哦靠我用的是你美注释的代码

不管用不用 await ,放入 Promise.all 里面都一样了吧

#13 这行代码会有问题,const promises = productList.map(u => ({tag: u, promise: hasStock(u)}))

#5 即使 hasStock 里面进行了 await 也不影响, 因为对于 hasStock 本身没有进行 await; 这里 startOrder 这个函数不会卡顿 (使用 "错误的处理"), 可能的一个原因是, 通过 node.js 处理时, 它会把所有 pending 的 promise 都处理完, 所以是卡在其他地方了. 比如下面这个代码:javascript

#5 代码忘了贴了:javascriipt// 需要订购的产品链接const productList = [ " xxx", " xxx", " xxx"]async function asyncSleep(duration) { await new Promise(r => setTimeout(r, duration));}// 是否有货async function hasStock(url) { await asyncSleep(2000); return false}// 开始订购const startOrder = async () => { const promises = productList.map(u => ({tag: u, promise: hasStock(u)})) const results = await Promise.allSettled(promises) for (const [i, result] of results.entries()) { // 是否有货,有就订购 if (!result.value) { console.log("无货", promises[i].tag) continue } }}function exitHandler(options, exitCode) { console.log("process exit:", performance.now());}process.on('exit', exitHandler.bind(null,{cleanup:true}));console.log("before:", performance.now());startOrder();console.log("after:", performance.now());

#16 为啥我的 markdown 没有渲染出来...

这个也不会阻塞的,只有加上 await 才会阻塞

这个方法本身允许在可迭代对象中放置非 promise 元素,所以楼上说传参错有问题的其实不对。MDN 文档里面有说:如果传入的 iterable 是非空的,但不包含待定的 promise ,则返回的 promise 仍然是异步兑现的,而不是同步兑现。所以错误的用法的兑现仍然受到整个运行时的事件循环的影响(调用 allSettled() 方法时会把 CPU 时间片让给其他的异步操作),如果其他操作很占用 CPU 或网络 IO ,那 Promise.allSettled() 本身就不能立刻兑现结果了。你考虑把上面的网络 IO 换成 setTimeout 这种,并减小列表长度,应该就可以“立刻”兑现了。文档: developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Global_Objects/Promise/allSettled#%E8%BF%94%E5%9B%9E%E5%80%BC