首页 > 解决方案 > NodeJs / Express:避免对许多文件进行顺序处理

问题描述

我有一个很少被调用的 Express webhook:

app.use('/convert', async (req, res) => {
  const files = await getFiles();
  for(let file of files) {
    await download(file);
    await convert(file);
    await upload(file)
  }
  res.send('finished');

}

循环的每次迭代需要几分钟,可能有数百个文件需要处理。我怎样才能在这里避免顺序处理?

非常感谢

标签: node.jsexpressmultiprocessing

解决方案


最简单的做法是同时处理所有内容。该Promise规范有一些方法可以同时处理多个 Promise,为此我们将要使用Promise.all.

app.use('/convert', async (req, res) => {
    const files = await getFiles();
    const promises = files.map(async (file) => {
        await download(file);
        await convert(file);
        await upload(file)
    });
    await Promise.all(promises);
    res.send('finished');
}

虽然一次完成所有事情相对简单,但它可能会占用大量资源。目前尚不清楚downloadconvertupload内部如何工作,但您很可能会达到机器资源的限制。为了避免达到打开文件限制或内存不足等问题,应该限制同时处理的项目数量。

一种方法是批量处理项目。要批量处理,您可以简单地将数组拆分files为块并将上面的解决方案与您的迭代解决方案结合起来。

app.use('/convert', async (req, res) => {
    const files = await getFiles();

    const chunkSize = 5;
    const chunks = [];
    while (files.length) {
        chunks.push(files.splice(0, chunkSize));
    }

    for (const chunk of chunks) {
        const promises = chunk.map(async (file) => {
            await download(file);
            await convert(file);
            await upload(file)
        });
        await Promise.all(promises);
    }
    res.send('finished');
});

上面的实现将等待chunkSize项目完成处理,然后再将其他项目排队chunkSize进行处理。因为它等待所有项目完成,所以一些项目可能处理得非常快,但其他项目需要更长的时间。在这种情况下,您最终会利用您的资源。理想情况下,您将始终一次处理chunkSize项目。为此,您可以将chunkSize“线程”排队等待处理,每个“线程”将一次处理一个项目,直到没有任何东西需要处理。

async function process(file) {
    await download(file);
    await convert(file);
    await upload(file);
}

async function thread(files) {
    while (files.length) {
        await process(files.pop());
    }
}

app.use('/convert', async (req, res) => {
    const files = await getFiles();

    let maxConcurrency = 5;

    const threads = [];
    while (--maxConcurrency) {
        threads.push(thread(files));
    }
    await Promise.all(threads);

    res.send('finished');
});

推荐阅读