如何修改此代码以防止选项卡崩溃



我有一段代码,它执行一长串http请求,我编写代码的方式是,它总是有4个请求并行运行。碰巧服务器可以最快地处理4个并行请求。代码越少,工作速度就越慢,请求越多,完成请求的时间就越长。无论如何,这是代码:

const itemsToRemove = items.filter(
// ...
)
const removeItem = (item: Item) => item && // first it checks if item isn't undefined
// Then it creates a DELETE request
itemsApi.remove(item).then(
// And then whenever a request finishes,
// it adds the next request to the queue.
// This ensures that there will always
// be 4 requests running parallel.
() => removeItem(itemsToRemove.shift())
)
// I start with a chunk of the first 4 items.
const firstChunk = itemsToRemove.splice(0, 4)
await Promise.allSettled(
firstChunk.map(removeItem)
)

现在,这个代码的问题是,如果列表很长(如数千项(,那么在某个时候浏览器选项卡就会崩溃。这有点没有帮助,因为我看不到具体的错误消息,告诉我出了什么问题。

但我的猜测是,这部分代码:

itemsApi.remove(item).then(
() => removeItem(itemsToRemove.shift())
)

可能正在创建Maximum call stack size exceeded问题?因为在某种程度上,我一直在添加到调用堆栈中,不是吗?

你认为我的猜测正确吗?不管你的答案是肯定还是否定,你知道我如何在不破坏浏览器选项卡的情况下实现同样的目标吗?我能以一种不添加到调用堆栈中的方式重构这段代码吗?(如果我真的这么做了?(

您的代码问题在中

await Promise.allSettled(firstChunk.map(removeItem)

根据文档,传递给Promise.allSettled的参数需要是Promises的数组

Promise.allSettled((方法返回一个在所有给定的承诺都已实现或被拒绝后实现的承诺,其中包含一个对象数组,每个对象描述每个承诺的结果。

然后,递归函数一个接一个地运行所有请求,抛出Maximum call stack size exceeded错误并使浏览器崩溃。

我想出的解决方案(可能会缩短(是这样的:

let items = []
while (items.length < 20) {
items = [...items, `item-${items.length + 1}`]
}
// A mockup of the API function that executes an asynchronous task and returns once it is resolved
async function itemsApi(item) {
await new Promise((resolve) => setTimeout(() => {resolve(item)}, 1000))
}
async function f(items) {
const itemsToRemove = items

// call the itemsApi and resolve the promise after the itemsApi function finishes
const removeItem = (item) => item &&
new Promise((resolve, reject) =>
itemsApi(item)
.then((res) => resolve(res))
.catch(e => reject(e))
)

// Recursive function that removes a chunk of 4 items after the previous chunk has been removed
function removeChunk(chunk) {
// exit the function once there is no more items in the array 
if (itemsToRemove.length === 0) return
console.log(itemsToRemove)
// after the first 4 request finish, keep making a new chunk of 4 requests until the itemsToRemove array is empty
Promise.allSettled(chunk.map(removeItem))
.then(() => removeChunk(itemsToRemove.splice(0, 4)))
}
const firstChunk = itemsToRemove.splice(0, 4)
// initiate the recursive function
removeChunk(firstChunk)
}
f(items)

我希望这能回答你的问题

最新更新