为什么 Promise 会有这种表现?
看下面代码,为什么使用“错误的处理”那种情况。明明所有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 ,放入 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
目前知道 iQOO 是 vivo 旗下的一个子品牌,定位游戏手机。上个月新出了 iQOO 8 和 iQOO 8 Pro,看着还挺香。但不知道实际使用体验如何,有用过的大佬说说是…
有一些史上最大的高科技公司的交易没有发生。有一些最有前途的产品和服务也没出现。为什么?因为这其中的人和公司当时都没有意识到是什么样的东西滑过了他们的手指,或者,他们只是简单地不…
以前在学校的时候很喜欢捣鼓,写玩具(比如模仿 github 上写简易 docker ,mit 6.s081 写简易 os ,写简单的 http 服务器),搬了两年砖,找不到当时…