使用 JavaScript/ES6 的 for 循环创建可通过 Promise.all 读取的 fetch Promise 数组?

Joe*_*per 1 javascript arrays es6-promise fetch-api

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

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

那么,计划是从 API 请求页面总数,然后将其输入到 for 循环中,以将多个获取请求推送到 Promise 数组中(即 link://to/api/data&page=1 、link://to/api/data&page=2 等)。然而,当我实际尝试使用 for 循环创建此数组时,该数组返回空。这是我的工作:

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;
});
Run Code Online (Sandbox Code Playgroud)

所以,真正让我困惑的是循环,以及它如何不返回一系列承诺。当我在控制台中查看它时,它显示为空白数组,但我可以扩展它并查看我期望的承诺。我看到“下面的值刚刚被评估”响应。然而,无论我写了多少个 Promise 或 .thens,该数组在运行时都不会实际填充。

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

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

lon*_*day 5

你这里有几个问题。

首先,您拥有提供给new Promise自身的函数,其中包含 Promise 创建。不要这样做!这是一种明确的反模式,并且不会保持代码干净。

第二个是基本代码:

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

这说:

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

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

因此,您需要在进行过程中将承诺添加到数组中,并在全部完成后解决整体承诺。

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);
}
Run Code Online (Sandbox Code Playgroud)

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

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);
}
Run Code Online (Sandbox Code Playgroud)