JavaScript中的承诺与循环:如何避免过多请求并同时运行

o75abkj4  于 2023-01-07  发布在  Java
关注(0)|答案(1)|浏览(98)

在过去的几天里,我试图解决一个涉及API请求和承诺的问题。首先,我使用Axios-rate-limit来管理每分钟最多30个请求。

const requestTiny = axiosRateLimit(axios.create({'baseURL': '*****'}), {maxRequests: 30, perMilliseconds: 60500})

主要函数为 syncProducts,如下所示:

export const syncProducts = async (req, res) => {
    let productsBN = []
    let products = await getProductsERP('BN')
    for (let prod of products) {
        const product = await getProductERP(prod.store, prod.id)
        productsBN.push(product)
    }
    res.status(201).json(productsBN)
}
  • getProductsERP* 返回ID,然后 getProductERP 返回每个产品的详细信息。BN 是商店。此代码完成此工作。我没有收到太多请求错误。

但是现在我需要从多个存储中获取数据。API请求限制是每个存储。所以,并行运行存储要快得多。
第一次尝试是为存储 ORL 复制某些行。正如预期的那样,代码逐行运行,第二个存储必须等待第一个存储完成。

export const syncProducts = async (req, res) => {
    let productsORL = [], productsBN = []
    let prodsBN = await getProductsERP('BN')
    for (let prod of prodsBN) {
        const product = await getProductERP(prod.store, prod.id)
        productsBN.push(product)
    }
    let prodsORL = await getProductsERP('ORL')
    for (let prod of prodsORL) {
        const product = await getProductERP(prod.store, prod.id)
        productsORL.push(product)
    }
    res.status(201).json(productsBN.concat(productsORL))
}

基于this,我尝试实现相同的逻辑,但使用Promises。

export const syncProducts = async (req, res) => {
    let productsORL = [], productsBN = []
    Promise.all([
        getProductsERP('ORL').then(async products => {
            productsORL = await Promise.all(products.map(async prod => await getProductERP(prod.store, prod.id)))
        }),
        getProductsERP('BN').then(async products => {
            productsBN = await Promise.all(products.map(async prod => await getProductERP(prod.store, prod.id)))
        })
    ])
    .then(res.status(201).json(productsBN.concat(productsORL)))
    .catch(error => res.status(409).json(error))
}

问题是当 getProductsERP 运行时,Axios速率限制工作良好,两个存储并行运行(预期行为)。当 getProductERP 运行时,它同时启动所有请求,导致“太多请求”错误。
我做错了什么?如何让 getProductERP 承诺遵守API限制?
PS:我试着尽可能多地恢复。如果我错过了一些重要的信息来评估解决方案,只要让我知道,我会更新代码。谢谢,

lyr7nygr

lyr7nygr1#

我觉得这就是你想要的。

// Gets products for one store, sequentially.
async function getProducts(storeCode) {
  const products = [];
  for (const {store, id} of await getProductsERP(storeCode)) {
    products.push(await getProductERP(store, id));
  }
  return products;
}

// Gets products for multiple stores in parallel.
export const syncProducts = async (req, res) => {
    const products = await Promise.all(getProducts('BN'), getProducts('ORL'));
    res.status(201).json(products.flat());
}

相关问题