如何在 promise 中实现 promise

How to do promise inside promise

我正在尝试使用 promise 进行分页。这是我的工作流程。

第 1 步:分页总页数为 50。url 将类似于 url?page=1

第 2 步: 在每个页面中,我将获得 50 个产品,我需要将其称为单独的 api。

唯一的条件是,在分页期间,仅当第一页的 50 api 调用完成后,才应调用第二页。获取所有 50 页后,它应该 return 承诺。

我目前所掌握的是

let promises = [];
paginate(50);
Promise.all(promises)
  .catch(function(err) {
  console.log('err',err);
  })
  .then(() => {
    console.log('All Done!!!!!');
});

function paginate(loop){
promises.push(
    axios(config)
    .then(function (response) {
        // Got 50 products
    })
    .catch(function (error) {
      console.log('err',err);
    })
)

Got 50 products 的地方,我仍然需要迭代 axios 中的 50 个产品。我不确定是否可以在承诺中做承诺。

由于服务器无法承受所有突如其来的负载,唯一的条件是只有在第一个(或前50个api被调用之后)才迭代第二个50个产品(或下一页的产品)。

编辑:

// 这里我有 50 个产品 正如我所说,在每个页面上我将获得 50 种产品,我将为所有这 50 种产品调用另一个 api。我已经给出了下面的代码。

唯一的限制是第一页响应,应该调用响应 50 的 api.. 就像 product?product=1 。接下来的 50 个应该只在前 50 个 api 被调用

之后被调用
for (let index = 0; index < response.length; index++) {
const element = response[index];
    //Here call api for one item 
    axios(config)
    .then(function (elemen t) {
        // Here i have got 50 products
    })
    .catch(function (error) {
      console.log('err',err);
    })
}

您可能不是在寻找 Promise.all (这意味着 运行 并行),但对于递归:

fetchPages(0, 49)
.then(console.log);

function fetchPages(from, to, results = []) {
  if (from <= to) {
    return fetchPage(from)
           .then(res => results.push(...res))
           .then(() => fetchPages(from + 1, to, results)); // calls itself
  } else {
    return results;
  }
}

function fetchPage(n) {
  console.log(`Fetching page ${n}`);
  // Here, you would return axios()...
  // But just for this demo, I fake that:
  const results = new Array(50).fill(null)
                               .map((_,i) => `Product ${i} from page ${n}`);
  return new Promise(resolve => setTimeout(() => resolve(results), 100));
}


编辑

上面的代码解决了页面只需要一个接一个获取的问题。我们可以保持 fetchPages 功能不变。现在,由于每个页面都包含需要单独获取的产品,我们只需编辑一下 fetchPage

有多种方法可以做到这一点。这里有一些:

解决方案 A:并行获取每个产品

如果服务器可以同时处理 50 个请求,您可以使用 Promise.all:

function fetchPage(n) {
  console.log(`Fetching page ${n}`);
  return axios(`/page?page=${n}`)
         .then(productIds => {
           return Promise.all(productIds.map(fetchProduct));
         });
}

function fetchProduct(id) {
  return axios(`/product?product=${id}`);
}

解决方案 B:按顺序获取每个产品

如果服务器无法同时处理多个请求,您可以再次使用递归:

function fetchPage(n) {
  console.log(`Fetching page ${n}`);
  return axios(`/page?page=${n}`)
         .then(fetchproducts);
}

function fetchProducts(productIds, results = []) {
  if (productIds.length) {
    const productId = productIds.shift();
    return fetchProduct(productId)
           .then(res => results.push(res))
           .then(() => fetchProducts(productIds, results)); // calls itself
  } else {
    return results;
  }
}

function fetchProduct(id) {
  return axios(`/product?product=${id}`);
}

解决方案 C:一次获取 X 个请求的产品

如果服务器可以同时处理 X 个请求,您可以使用像 queue 这样的模块,它可以帮助您实现并发:

const queue = require('queue'); // Don't forget to $ npm install queue
const MAX_CONCURRENT_CALLS = 4; // 4 calls max at any given time

function fetchPage(n) {
  console.log(`Fetching page ${n}`);
  return axios(`/page?page=${n}`)
         .then(fetchproducts);
}

function fetchProducts(productIds) {
  const q = queue();
  q.concurrency = MAX_CONCURRENT_CALLS;
  const results = [];

  q.push(
    ...productIds.map(productId => () => {
      return fetchProduct(productId)
             .then(product => results.push(product));
    })
  );

  return new Promise((resolve, reject) => {
    q.start(function (err) {
      if (err) return reject(err);
      resolve(results);
    });
  });
}

function fetchProduct(id) {
  return axios(`/product?product=${id}`);
}