javascript - 如何在 promise 中履行 promise

标签 javascript node.js promise axios es6-promise

我正在尝试有希望地进行分页。这是我的工作流程。

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

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

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

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

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);
    })
}

最佳答案

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

关于javascript - 如何在 promise 中履行 promise ,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/63859466/

相关文章:

javascript - 在 Bluebird Promise 中动态定义函数

javascript - 更改 FullCalendar jQuery 插件中的默认事件单元格 View

python - 部署云函数时index.js出错

mysql - 在 Node.js 中管理数据库连接,最佳实践?

node.js - 快速请求处理程序中的 q-io/fs

node.js - 如何 promise Braintree 方法?

javascript - 将 Lit 元素移动到新文档时未保留样式

javascript - 从时间戳创建 UUID(作为数字)

javascript - Jquery UI slider 和自定义样式

javascript - Node.js & co - 避免混合 promise 和事件回调