2016-11-11 2 views
1

с типичной постраничной API, который возвращаетнерекурсивна пагинация обещаний

{ 
    "data": ..., 
    "nextPageHref": <url> 
} 

как я могу извлечь все страницы в JavaScript без использования рекурсии?

(рекурсивное решение что-то вроде)

fetchPaginated(url) { 
    return fetch(url).then(result => result.nextPageHref 
    ? fetchPaginated(result.nextPageHref).then(results => _.concat(result, results)) 
    : result 
} 
+0

Почему вы хотите сделать это без рекурсии? –

+0

более дорогие трассировки стека и JS не являются хвостовыми рекурсивными (по крайней мере, не везде, а не на время). – JonathanR

+0

Если вы используете то, что мне нужно, я считаю, что надлежащая библиотека specs Promise должна делать что-то похожее слишком nextTick, поэтому ваш стек должен очистить. Если это то, что вы подразумеваете под «более приятными стековыми следами». – Keith

ответ

2

AFAIK единственный способ сделать это без рекурсии - это встроенная поддержка async-wait и использование цикла for. Обратите внимание, что скомпилированный async-wait будет компилироваться и с некоторым замаскированным рекурсивным кодом.

Но эта рекурсия не является рекурсией, так как вызов от fetchPaginated вызывается из обратного вызова, поэтому стек вызовов синхронизации всегда будет очищен до обратного вызова (и, следовательно, он мало связан с рекурсией хвоста). Если вас беспокоит стеки вызовов асинхронных браузеров (которые существуют только для целей отладки, нам не нужен стек вызовов async для запуска программы), я думаю, что в инструментах разработчика браузеров должен быть флажок, чтобы отключить его ,

enter image description here

+0

Это действительно хороший момент, когда вызывающая функция будет выполнена до того, как произойдет рекурсивный вызов. Спасибо! – JonathanR

+0

действительно хороший пошаговое объяснение [здесь] (http://stackoverflow.com/a/37406665/3099140) – JonathanR

0

Я думаю, вы могли бы послать общее количество страниц, на прошу страницу - /get_page?page_num=4:

{ 
    "data": ..., 
    "number_of_pages": 73 
} 

это даст вам знать, если вы можете запросить страницу 5.

Кроме того, у нее есть преимущество, что вы можете позволить пользователю пропустить 5 страниц или получить доступ к последней странице, которую вы не можете сделать с помощью ch вы предложили.

+0

Мой API поддерживает только разбиение на страницы на основе токенов. Я должен получить страницу 'n', чтобы иметь возможность извлекать страницу' n + 1' (обратите внимание, что многие API-интерфейсы реальной жизни, такие как google и facebook, следуют этому шаблону, чтобы гарантировать, что люди фактически используют разбиение на страницы, а не обходят его, запрашивая каждую страницу одновременно) – JonathanR

+0

@JonathanR Тогда почему вы хотите обойти разбивку на страницы? –

+0

вы можете назначить текущую страницу токену, а затем просто используйте '/ get_next_page', чтобы получить следующую страницу и'/get_first_page', чтобы сбросить счетчик. –