使用带有 JavaScript/ES6 的 for 循环创建一个获取承诺数组,可以通过 Promise.all 读取?

Create an array of fetch promises using a for loop with JavaScript/ES6 that can be read via Promise.all?

因此,为了不让任何人对背景故事感到厌烦,我需要访问来自多个 API 的数据,以便 运行 我的脚本。在我执行脚本之前需要加载所有数据,我通常很乐意这样做:我只是声明一些获取请求,写一个 Promise.all,然后继续执行该函数。

但是,我遇到了一些问题 API,这将我可以从一个请求中提取的结果数量限制为 100 个,我需要查询所有结果。我不认为这有什么大不了的,因为我认为我可以通过在请求末尾附加“&page=X”来提出几个额外的请求。

然后,计划是从 API 请求总页数,然后将其送入 for 循环以将多个获取请求推送到承诺数组(即 link://to/api/data&page=1,link://to/api/data&page=2,等等)。但是,当我实际尝试使用 for 循环创建此数组时,数组 returns 为空。这是我的作品:

const dataUrlNoPage = 'link/to/api/data&page=';
const totalPages = 3; //usually pulled via a function, but just using a static # for now

let apiRequestLoop = function(inp) {
  return new Promise(function(resolve){
    let promiseArray = [];
    for (let i = 1; i <= inp; i++) {
      let dataUrlLoop = dataUrlNoPage + i;
      fetch(dataUrlLoop).then(function(response){
        promiseArray.push(response.json());
      })
     }
    resolve(promiseArray);
  })
}

let finalPromiseArray = apiRequestLoop(totalPages).then(result => {
  let requestArray = [apiRequest1,apiRequest2];
  //requestArray contains earlier fetch promises
  result.forEach(foo => {
    requestArray.push(foo);
    }
  );
  return requestArray;
});

所以,真正让我感到困惑的是循环,以及它如何不返回一系列承诺。当我在控制台中查看它时,它显示为一个空白数组,但我可以展开它并看到我期望的承诺。我看到 "Value below was evaluated just now" 响应。然而,无论有多少 promises 或 .thens,我写的是,数组从未在 运行 时间实际填充。

这是怎么回事?我不能通过 for 循环生成提取承诺吗?

(另外,为了稍微打断这一行问题,是的,我尝试访问的 API 是 Wordpress。环顾四周,大多数人建议创建一个自定义端点,但让我们假设为了这个项目的目的,我被禁止这样做。)

几点:

  • 您实际上想将 promise 本身放入数组中,而不是推送到与 promise 链接的 .then() 中的数组。
  • 您可能想跳过在函数中创建新的 Promise。只需从循环中获取所有承诺的数组,然后在数组上 return 一个 Promise.all

像这样:

let apiRequestLoop = function(inp) {
  let promiseArray = [];
  for (let i = 1; i <= inp; i++) {
    let dataUrlLoop = dataUrlNoPage + i;
     promiseArray.push(fetch(dataUrlLoop))
  }
  return Promise.all(promiseArray);
}

在您最后的 .then 语句中,在 finalPromiseArray 中,您的结果将是所有承诺结果的数组。像这样 [response1, response2, response3, ...]

有关详细信息,请参阅 Promise.all documentation

你这里有几个问题。

首先,您拥有提供给 new Promise 的函数,它本身包含 promise 的创建。不要这样做!这是一个明确的 anti-pattern 并且不会使您的代码保持整洁。

第二个是这段基本代码:

let promiseArray = [];
for (let i = 1; i <= inp; i++) {
  let dataUrlLoop = dataUrlNoPage + i;
  fetch(dataUrlLoop).then(function(response){
    promiseArray.push(response.json());
  })
 }
resolve(promiseArray);

这表示:

  1. 创建一个空数组
  2. 遍历另一个数组,执行 HTTP 请求
  3. 用空数组解决你的承诺
  4. 当 HTTP 请求完成后,将它们添加到数组中

第四步总是在第三步之后。

因此,您需要在进行过程中将 promises 添加到您的数组中,并在它们全部完成时解决整个 promise。

let apiRequestLoop = function(inp) {
  let promiseArray = [];
  for (let i = 1; i <= inp; i++) {
    let dataUrlLoop = dataUrlNoPage + i;
    promiseArray.push(fetch(dataUrlLoop).then(function(response) {
      return response.json();
    }));
  }
  return Promise.all(promiseArray);
}

或者,使用箭头函数来清理:

let apiRequestLoop = function(inp) {
  let promiseArray = [];
  for (let i = 1; i <= inp; i++) {
    let dataUrlLoop = dataUrlNoPage + i;
    promiseArray.push(fetch(dataUrlLoop).then(response => response.json()));
  }
  return Promise.all(promiseArray);
}