继续取数据直到结果为空数组

Continue fetching data until result is empty array

我正在使用 Selly API 并尝试获取所有产品,但是 Selly API 对产品进行分页。

所以我需要获取所有产品并添加到一个数组中,然后通过JSON输出结果。

const base64 = require('base-64');
import fetch from 'isomorphic-unfetch';

export default async (req, res) => {
    res.setHeader('Content-Type', 'application/json');
    try {
        request('products')
            .then(data => data.json())
            .then(json => res.status(200).end(JSON.stringify(json)));
    } catch(err) {
        res.end(JSON.stringify({
            "error": err
        }));
    }
}

const getToken = () => {
    return base64.encode(`${process.env.api.email}:${process.env.api.key}`);
}

const request = async (endpoint = '', page) => {
    const options = {
        headers: {
            Authorization: `Basic ${getToken()}`,
            'User-Agent':  `${process.env.api.email} - https://example.com`
        }
    }
    return fetch(`https://selly.io/api/v2/${endpoint}?page=${page}`, options);
}

我正在尝试获取 https://selly.io/api/v2/products?page=${page},直到 return 结果为空数组 []

我的尝试是这样的:

const repeatedRequest = async (data, endpoint) => {
    let i = 1;
    while (data.length > 0) {
        console.log(data);
        await request(endpoint, i).then((res) => {
            data.push(res);
            i++;
        });
    }
    return data;
}

但是这不起作用,因为 return 结果是一个空数组。我也很困惑我将如何与以下代码片段一起执行此操作:

request('products')
    .then(data => data.json())
    .then(json => res.status(200).end(JSON.stringify(json)));

我将如何在函数中工作?

我该怎么做?

您(在评论中)问了一个关于如何设置循环以一遍又一遍地调用请求函数以获得结果直到没有更多结果的子问题。我将尝试以最小和通用的方式在这里回答您的子问题,希望对您和其他人有用。

这是一种单独设置异步循环机制的方法。总是有不止一种方法。 ;)

我将制作几个实用函数,让我能够简洁地表达解决方案。

  1. 我需要一个伪造的 request 函数,它将 return 一些结果,然后 return 一些虚假的东西。我称之为 fakeRequest.
  2. 我需要一种通用的方法来调用带有不断增加的整数索引参数的异步函数,直到它 return 像 异步生成器函数 一样虚假。我称之为 iterateAllAsync
  3. 我需要一种通用方法来将异步生成器函数的所有结果合并到一个数组中。本质上是 Array.from 的异步版本。我称之为 arrayFromAsync

然后你可以说:i = 0 开始并递增 i 直到它没有 return 任何东西然后 return所有这些结果作为数组.

...您可以(大致)表示为:arrayFromAsync(iterateAllAsync(fakeRequest))。在实践中,我可能会添加一个 lambda 来向您展示如何将一些额外的参数柯里化到 fakeRequest,但这是它的基本结构。

完整内容如下:

// An example fake request function
const fakeRequest = async (endpoint, i) => {
  const kNumberOfFakeResultsToReturn = 3;
  if (i >= kNumberOfFakeResultsToReturn) return;
  return { content: `fake payload #${i} from ${endpoint}` };
};

// A general purpose utility function:
// yields results of calling fn(i) with ever increasing i until it returns something falsey
async function* iterateAllAsync(fn, i = 0) {
  while (true) {
    let res = await fn(i)
    if (!res) return;
    yield res;
    ++i;
  }
}

// A general purpose utility function:
// returns an async generator's results as an array
const arrayFromAsync = async (it) => {
  let results = [];
  for await (let res of it) {
    results.push(res);
  }
  return results;
}

// Here's where we describe what we want done:
arrayFromAsync(iterateAllAsync((i) => fakeRequest('fakeEndpoint', i)))
  .then(console.log);