Firebase 功能因 Promise 而停止

问题描述 投票:0回答:1

我有一个 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 分钟。

javascript firebase promise google-cloud-functions
1个回答
0
投票

我不会尝试修复您的代码,而是建议采用不同的方法:

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 函数,但实现为迭代器而不仅仅是数组。

© www.soinside.com 2019 - 2024. All rights reserved.