我有一个 firebase https 函数(使用 onRequest)。它获取 3800 个类别,并将它们批处理为 Promise。
let categoryCount = 0
while (categories.length) {
await Promise.all([
...categories.splice(0, 5).map((category) => {
const { id, level } = category
let productCountPromise = null
// *- Only check for level 3 and above
if (level >= 3) {
productCountPromise = getProductCount(appId, id)
}
categoryCount += 1
return productCountPromise
? productCountPromise.then((productCount) => {
console.log(`Category: ${id} Level: ${level} Count: ${productCount}`)
if (productCountPromise <= 0) {
categoryIdsToHide.push(id)
} else if (productCountPromise > 0) {
categoryIdsToShow.push(id)
}
})
: productCountPromise
}),
() => new Promise((resolve) => setTimeout(resolve, 1000)),
])
}
此函数运行 5 个 HTTP 请求并等待 1000 毫秒以便 API 可以恢复。 API 没有超时,但 firebase 函数只是停止并且永远不会超过此 while 循环。我是否还有未完成的承诺?该函数将运行大约 6 分钟,并在不同数量的类别上停止。
没有错误,v2 firebase 函数的超时设置为 60 分钟。
我不会尝试修复您的代码,而是建议采用不同的方法:
const categories = [
{ id: '1', level: 2 },
{ id: '2', level: 5 },
{ id: '3', level: 1 },
{ id: '4', level: 7 },
];
// Define a couple of helper functions: take and filter
function* take(n, iter) {
let { value, done } = iter.next();
while (n > 0 && n-- && !done) {
yield value;
({ value, done } = iter.next());
}
}
function* filter(pred, iter) {
let { value, done } = iter.next();
while (!done) {
if (pred(value))
yield value;
({ value, done } = iter.next());
}
}
// iterator is stateful, no need to splice array
// we can also lazily yield up only the categories
// that pass the level check.
const categoriesIterable = filter(
({ level }) => level >= 3,
categories[Symbol.iterator](),
);
const categoriesIter = categoriesIterable[Symbol.iterator]();
let batch = [...take(5, categoriesIter)];
const idsToHide = [];
const idsToShow = [];
while (batch.length) {
// NOTE: top-level await only works in ES module files.
// if you need this to work in commonJS wrap in an
// async function or IIFE
await Promise.all(batch.map(async ({ id }) => {
const count = await getProductCount(id, appId);
if (count) {
idsToShow.push(id);
}
else {
idsToHide.push(id);
}
}));
// wait 1 sec
await new Promise((res) => setTimeout(res, 1000));
// queue up the next batch
batch = [...take(5, categoriesIter)];
}
这使用生成器和迭代器一次使用数组 5 中的类别并处理它们。请注意,除了辅助函数之外,代码非常简单。助手本身基本上只是 lodash 函数,但实现为迭代器而不仅仅是数组。