Рекомендуемый шаблон для постраничного ответа API до исчерпания? - PullRequest
0 голосов
/ 01 октября 2019

Я новичок в Node и модели асинхронного программирования. У меня возникают проблемы, связанные с простым требованием, которое кажется довольно базовым в синхронных средах: пролистывание ответа API до тех пор, пока ответ не станет пустым.

В частности, API при успешном вызове вернет данные истатус 200 или 206 (частичное содержание). Если я вижу ответ 206, мне нужно продолжать вызывать API (также отправляя параметр запроса page, который я увеличиваю каждый раз), пока не увижу ответ 200.

На синхронном языкеЗадача будет очень простой:

// pseudocode
data = []
page = 1
do {
    response = api.call(page)
    data.append(response.data)
    page++
} while (response != 200)

return data

Теперь в Node для одного вызова API будет работать такой код:

// fire when '/' has a GET request
app.get('/', (req, res) => {
    axios.get('https://api.com/v1/cats')
        .then(response => {
            // now what??
        });
    });
});

См. комментарий //now what??? Это та точка, где мне интересно, как действовать дальше. Я наткнулся на этот несколько релевантный пост, но не смог преобразовать его в формат, который будет работать для меня в Node и Axios.

Достаточно ли просто обернуть код аксиоса вотдельная функция? Я так не думаю, потому что если я сделаю это:

function getData(pageNum) {
    axios.get('https://api.com/v1/cats')
        .then(response => {
            // now what??
        });
    });
}

Я не могу рассчитывать на возвращаемое значение, потому что, как только axios.get() будет выполнено, функция будет завершена. Я могу позвонить getData() снова после получения первого ответа, но затем, предположим, я хочу вернуть все данные из этих многочисленных вызовов в виде ответа HTTP от моего сервера Express. ,,как мне это сделать?

Надеюсь, я не буду обижаться за лень или что-то в этом роде. Я действительно огляделся, но ничего не нашел.

1 Ответ

1 голос
/ 01 октября 2019

Во-первых, встречный вопрос: настолько ли велик набор данных, что вам нужно беспокоиться об использовании всей памяти? Потому что, если это так, то потребуется больше усилий для структурирования вашего кода таким образом, чтобы данные проходили на всем протяжении. (На самом деле, я даже не уверен, позволяет ли Express потоковую передачу ... вы используете Express, не так ли?)

Из документации Axios выглядит, что response - читаемый поток, который обеспечиваеттело ответа. Так что чтение это тоже асинхронная задача. Таким образом, вы должны написать функцию, которая делает это. Смотрите страницу "Stream" документации по nodejs для более подробной информации. Или я могу убедить помочь с этим, если позволяет время. Но сейчас я предполагаю, что у вас есть функция readResponse, которая принимает объект ответа axios в качестве аргумента и возвращает обещание, и обещание разрешается в объект, такой как { statusCode: 206, result: ['thing1', 'thing2'] }. Я также предполагаю, что ваша цель состоит в том, чтобы собрать все result массивы и объединить их вместе, например, ['thing1', 'thing2', 'thing3', 'thing4', 'thing5', 'thing6'].

. Вы можете написать самозвонящую версию своей функции getData. Это будет извлекать все данные с данной страницы и далее (не только саму страницу):

function getData(pageNum) {
    axios.get('https://api.com/v1/cats' + (pageNum ? '?page=' + pageNum) : '')
        .then(readResponse)
        .then(function(parsedResponse) {
            if(parsedResponse.statusCode == 200) {
                return parsedResponse.result;
            } else if(parsedResponse.statusCode == 206) {
                return getData(pageNum + 1).then(function(laterData) {
                    return parsedResponse.result.concat(laterData);
                });
            } else {
                // error handling here, throw an exception or return a failing promise.
            }
        });
    });
}

Затем, чтобы получить все данные, просто вызовите эту функцию с помощью pageNum = 0:

// fire when '/' has a GET request
app.get('/', (req, res) => {
    getData(0)
        .then(function(results) {
            // results is now the array you want.
            var response = JSON.stringify(results);   // or whatever you're doing to serialise your data
            res.send(response);
        });
});
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...