【问题标题】:How to do promise inside promise如何在promise里面做promise
【发布时间】:2020-12-30 17:01:24
【问题描述】:

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

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

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

唯一的条件是,在分页期间,只有在第一页的 50 api 调用完成时才应该调用第二页。获取所有 50 个页面后,它应该返回承诺。

到目前为止我所拥有的是。

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 个产品。我不确定是否可以在 promise 中做 promise。

由于服务器无法承受突然的负载,唯一的条件是在第一个(或前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);
    })
}

【问题讨论】:

    标签: javascript node.js promise axios es6-promise


    【解决方案1】:

    您可能不是在寻找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}`);
    }
    

    【讨论】:

    • 嗨,感谢您的回答.. 在 // Got 50 products, 我将为 1 个产品调用每个 api.. 就像一页它将是 50 个调用等等.. . 抱歉,我将编辑问题并更具体.. .
    • @SA__ 好的,我编辑了我的答案。我认为解决方案 C 是最好的,因为它允许您微调您希望在任何给定时间发出的最大请求数,以最小化服务器负载,但仍然能够有一些并发性
    • 嗨@blex 非常感谢你,我将使用解决方案c..非常感谢
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2019-03-17
    • 2018-05-14
    • 2017-03-09
    • 1970-01-01
    • 1970-01-01
    • 2018-09-16
    • 1970-01-01
    相关资源
    最近更新 更多