Почему предыдущая страница работает, только если есть 2 страницы (API Google Диска)

Я столкнулся с проблемой, возможно, это не что-то огромное. Итак, в основном я использую API Google Диска для извлечения файлов с диска, и я хочу сделать разбиение на страницы, мне удалось сделать следующую страницу очень хорошо, но проблема возникла, когда я попытался реализовать кнопку Previous Page. Мне удалось заставить его работать, но теперь, если есть 2 страницы, он работает просто отлично, но если их больше 2, например, если есть 3 страницы, если я перехожу на 3-ю страницу, нажмите кнопку Previous Page, я перехожу на 2-ю страницу , но тогда нет "previousPageToken", поэтому кнопка вообще не появляется. Должен ли я хранить токены в массиве или что-то в этом роде? Вот код:


let currentPageToken = null;
let previousPageToken = null;

async function listFiles(folderId, pageToken = null) {
  $('#table_content').empty();
  $('#table_content').remove();
  isListFilesInProgress = true; // Set the flag to indicate listFiles() is in progress

  // Disable the button during listFiles() execution
  $('#show_files_button').prop('disabled', true);

  const request = {
    q: `'${folderId}' in parents`,
    pageSize: 10,
    fields: 'nextPageToken, files(id, name, mimeType, thumbnailLink, webContentLink, modifiedTime)',
    pageToken: pageToken, // Pass the pageToken to retrieve the next page
  };

  gapi.client.drive.files
    .list(request)
    .then(function (response) {
      console.info(response);
      var files = response.result.files;
      if (files && files.length > 0) {
        var table = document.createElement('table');
        table.classList.add('table', 'table-striped');
        table.id = 'table_content';

        var thead = document.createElement('thead');
        var headerRow = document.createElement('tr');
        var header1 = document.createElement('th');
        header1.textContent = 'Thumbnail';
        var header2 = createSortableHeader('Name', 'name');
        var header3 = createSortableHeader('Type', 'mimeType');
        var header4 = createSortableHeader('Last Updated', 'modifiedTime');
        var header5 = document.createElement('th');
        header5.textContent = 'Download';

        headerRow.appendChild(header1);
        headerRow.appendChild(header2);
        headerRow.appendChild(header3);
        headerRow.appendChild(header4);
        headerRow.appendChild(header5);
        thead.appendChild(headerRow);
        table.appendChild(thead);

        var tbody = document.createElement('tbody');
        for (var i = 0; i < files.length; i++) {
          (function (file) {
            var fileName = file.name;
            var mimeType = file.mimeType;
            var thumbnailLink = file.thumbnailLink;
            var downloadLink = file.webContentLink;
            var lastUpdated = new Date(file.modifiedTime).toLocaleString();
            var fileId = file.id;

            var row = document.createElement('tr');

            var thumbnailCell = createThumbnailCell(thumbnailLink, mimeType, fileId);
            row.appendChild(thumbnailCell);

            var nameCell = document.createElement('td');
            nameCell.textContent = fileName;
            row.appendChild(nameCell);

            var typeCell = document.createElement('td');
            typeCell.textContent = mimeType;
            row.appendChild(typeCell);

            var lastUpdatedCell = document.createElement('td');
            lastUpdatedCell.textContent = lastUpdated;
            row.appendChild(lastUpdatedCell);

            if (mimeType != 'application/vnd.google-apps.folder') {
              var downloadCell = document.createElement('td');
              var downloadLinkElem = document.createElement('a');
              downloadLinkElem.href = downloadLink;
              downloadLinkElem.textContent = 'Download';
              downloadLinkElem.classList.add('btn', 'btn-primary');
              downloadLinkElem.target = '_blank';
              downloadCell.appendChild(downloadLinkElem);
              row.appendChild(downloadCell);
            }

            // Add click event listener to navigate into folders
            if (mimeType === 'application/vnd.google-apps.folder') {
              row.classList.add('folder-row');
              row.addEventListener('click', function () {
                var folderId = file.id;
                listFiles(folderId);
              });
            }

            tbody.appendChild(row);
          })(files[i]);
        }

        table.appendChild(tbody);
        document.getElementById('content').appendChild(table);

        // Remove existing Next Page and Previous Page buttons
        $('.next-page-button').remove();
        $('.previous-page-button').remove();

        // Add Next Page button if there is a nextPageToken
        const nextPageToken = response.result.nextPageToken;
        if (nextPageToken) {
          const nextPageButton = document.createElement('button');
          nextPageButton.textContent = 'Next Page';
          nextPageButton.classList.add('btn', 'btn-primary', 'next-page-button');
          nextPageButton.addEventListener('click', function () {
            listFiles(folderId, nextPageToken); // Call listFiles() with the nextPageToken
          });

          document.getElementById('content').appendChild(nextPageButton);
        }

        // Add Previous Page button if there is a pageToken
        if (pageToken) {
          const previousPageButton = document.createElement('button');
          previousPageButton.textContent = 'Previous Page';
          previousPageButton.classList.add('btn', 'btn-primary', 'previous-page-button');
          previousPageButton.addEventListener('click', function () {
            listFiles(folderId); // Call listFiles() without the pageToken to go back to the previous page
          });

          document.getElementById('content').appendChild(previousPageButton);
        }
      }
    })
    .finally(function () {
      isListFilesInProgress = false;
      $('#show_files_button').prop('disabled', false);
    });
}

Подводя итог, я могу вернуться только на одну страницу назад, и она останавливается там, поэтому я могу нормально перейти на следующую страницу, потому что для следующей страницы всегда есть токен.

Заранее спасибо!

Редактировать:

Итак, как было предложено, я попытался сохранить токены страницы в массиве, я помещаю его в массив, и при следующем вызове функции (при нажатии следующей страницы) токен берется из массива, и я проверял с помощью console.info(), что токен назначен previousPageToken, но по какой-то причине на следующей странице, когда я нажимаю кнопку «Предыдущая страница», теперь просто обновляется та же страница, это код создания кнопки:

const previousPageToken = pageTokens[pageTokens.length - 1];

          console.info('next');
          console.info(nextPageToken);
          console.info('previous');
          console.info(previousPageToken);
          
          if (previousPageToken) {
            const previousPageButton = document.createElement('button');
            previousPageButton.textContent = 'Previous Page';
            previousPageButton.classList.add('btn', 'btn-primary', 'previous-page-button');
            previousPageButton.addEventListener('click', function () {
              listFiles(folderId, previousPageToken); // Call listFiles() with the previousPageToken
            });

            document.getElementById('content').appendChild(previousPageButton);
          }

Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Улучшение производительности загрузки с помощью Google Tag Manager и атрибута Defer
Улучшение производительности загрузки с помощью Google Tag Manager и атрибута Defer
В настоящее время производительность загрузки веб-сайта имеет решающее значение не только для удобства пользователей, но и для ранжирования в...
Безумие обратных вызовов в javascript [JS]
Безумие обратных вызовов в javascript [JS]
Здравствуйте! Юный падаван 🚀. Присоединяйся ко мне, чтобы разобраться в одной из самых запутанных концепций, когда вы начинаете изучать мир...
Система управления парковками с использованием HTML, CSS и JavaScript
Система управления парковками с использованием HTML, CSS и JavaScript
Веб-сайт по управлению парковками был создан с использованием HTML, CSS и JavaScript. Это простой сайт, ничего вычурного. Основная цель -...
JavaScript Вопросы с множественным выбором и ответы
JavaScript Вопросы с множественным выбором и ответы
Если вы ищете платформу, которая предоставляет вам бесплатный тест JavaScript MCQ (Multiple Choice Questions With Answers) для оценки ваших знаний,...
0
0
68
2
Перейти к ответу Данный вопрос помечен как решенный

Ответы 2

При проверке общей логики того, чего вы пытаетесь достичь, рекомендуемый подход действительно заключается в сохранении nextPageToken в массиве, чтобы его можно было вызвать позже. Теоретически достаточно просто использовать array.push(), это также позволит вам перемещаться по индексу массива, поскольку вы будете точно знать, что новый «nextPageToken» будет добавлен в конец массива. Я могу порекомендовать просмотреть ответ Танайке в этом посте, чтобы использовать его в качестве справки для управления токенами:

    async function main(auth) {
  const drive = google.drive({ version: "v3", auth });

  const fileList = [];
  let NextPageToken = "";
  do {
    const params = {
      // q: "",  // In this case, this is not required.
      orderBy: "name",
      pageToken: NextPageToken || "",
      pageSize: 1000,
      fields: "nextPageToken, files(id, name)",
    };
    const res = await drive.files.list(params);
    Array.prototype.push.apply(fileList, res.data.files);
    NextPageToken = res.data.nextPageToken;
  } while (NextPageToken);

  console.info(fileList.length);  // You can see the number of files here.
}

В качестве примечания, имейте в виду, что nextPageTokens недолговечны, согласно моему опыту и опыту других пользователей Stackoverflow (например, Linda Lawton - DaImTo ), они длятся около часа

Использованная литература:

Эй, поэтому я изменил функцию, так что теперь токены предыдущих страниц хранятся в массиве, при следующем вызове функции я назначаю последний элемент в массиве previousPageToken, но теперь кнопка по какой-то причине только обновляет страницу (я редактировал вопрос с кодом)

Laimonas Rupeika 30.05.2023 13:31
Ответ принят как подходящий

Итак, мне наконец удалось решить эту проблему, поэтому я опубликую ответ, может быть, кто-то найдет это полезным. Прежде всего, я использовал массив для хранения токена текущей страницы на каждой странице. При нажатии кнопки «Предыдущая страница» я удаляю последний элемент в массиве. Вот код:


// Add Previous Page button if there is a previousPageToken
        var previousPageToken = pageTokens[pageTokens.length - 1];
        if (pageTokens.length != 0)
        {
          if (previousPageToken) {
            const previousPageButton = document.createElement('button');
            previousPageButton.textContent = 'Previous Page';
            previousPageButton.classList.add('btn', 'btn-primary', 'previous-page-button');
            previousPageButton.addEventListener('click', function () {
              pageTokens = pageTokens.slice(0, -1);
              listFiles(folderId, previousPageToken); // Call listFiles() with the previousPageToken
            });
            document.getElementById('content').appendChild(previousPageButton);
          }
          else if (previousPageToken == null) {
            const previousPageButton = document.createElement('button');
            previousPageButton.textContent = 'Previous Page';
            previousPageButton.classList.add('btn', 'btn-primary', 'previous-page-button');
            previousPageButton.addEventListener('click', function () {
              pageTokens = [];
              listFiles(folderId); // Call listFiles()
            });
            document.getElementById('content').appendChild(previousPageButton);
          }
        }

        // Add Next Page button if there is a nextPageToken
          const nextPageToken = response.result.nextPageToken;
          if (nextPageToken) {
            const nextPageButton = document.createElement('button');
            nextPageButton.textContent = 'Next Page';
            nextPageButton.classList.add('btn', 'btn-primary', 'next-page-button');
            nextPageButton.addEventListener('click', function () {
              pageTokens.push(pageToken);
              listFiles(folderId, nextPageToken); // Call listFiles() with the nextPageToken
            });

            document.getElementById('content').appendChild(nextPageButton);
          }

Затем я понял, что по какой-то причине я не могу получить токен первой страницы (он был сохранен как нуль в массиве). Поэтому я сделал отдельный else if для случая, когда последним элементом в массиве является null, что означало, что это была 2-я страница. Поэтому, когда я вызываю свою функцию без токена страницы, которая по умолчанию загружает первую страницу. Я также сделал галочку if (pageTokens.length != 0), чтобы кнопка «Предыдущая страница» не отображалась, если это первая страница.

Другие вопросы по теме