英文:
Why previous page only works if there's 2 pages (Google Drive API)
问题
Sure, here is the translated code part:
我遇到了一个问题,可能不是什么大问题。基本上,我正在使用Google Drive API从Drive检索文件,我想要进行分页,我成功地做到了下一页,但当我尝试实现“上一页”按钮时出现了问题。我设法让它工作,但现在如果有2页,它就运行正常,但如果有超过2页,例如,如果有3页,如果我进入第3页,然后点击“上一页”按钮,它会带我到第2页,但然后没有“previousPageToken”,所以按钮根本不显示。我应该将令牌存储在数组中吗?
以下是代码:
// 在这里插入你的代码
总结一下,我只能返回一页,然后停在那里,因此我可以轻松地转到下一页,因为始终有下一页的令牌。
谢谢您提前帮助!
编辑:
所以正如建议的,我尝试将页面令牌保存在一个数组中,我将它推送到数组中,在下一个函数调用时(当点击下一页时),令牌从数组中取出,我通过`console.log()`检查了令牌是否赋值给`previousPageToken`,但由于某种原因,在下一页上,当我按下上一页按钮时,它现在只是刷新同一页,这是按钮创建的代码:
// 在这里插入你的代码
如果需要进一步的帮助或解释,请随时告诉我。
英文:
I've encountered a problem, probably it's not something huge. So basically I'm using Google Drive API to retrieve files from drive and I want to make pagination, I managed to do next page just fine, but the problem rised when I tried implementing Previous Page
button. Imanaged to make it work, but now if there's 2 pages it works just fine, but if there's more than 2, for example, if there are 3 pages, if I go to 3rd page, click Previous Page
button, it takes me to 2nd page, but then there's no "previousPageToken"
so button is not appearing at all. Should I store tokens in an array or something like that?
Here is the code:
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.log(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);
});
}
To sum up, I can only go back one page and it stops there, therefore I can go to next page just fine, because there is always a token for next page.
Thank you in advance!
Edit:
So as suggested I tried keeping page tokens in an array, I push it into an array and on the next function call (when next page is clicked), token is taken from array and I checked with console.log()
that token is assigned to previousPageToken
, but for some reason on the next page when I press Previous Page button it now just refreshes same page, this is the code of button creation:
const previousPageToken = pageTokens[pageTokens.length - 1];
console.log('next');
console.log(nextPageToken);
console.log('previous');
console.log(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);
}
答案1
得分: 1
测试您试图实现的整体逻辑时,推荐的方法确实是将 nextPageToken 保存在数组中,以便稍后调用。理论上,只需使用 array.push() 就足够了,这也将允许您浏览数组索引,因为您肯定知道新的 'nextPageToken' 将添加到数组的末尾。
我建议参考 Tanaike 在 这个帖子 中的答案,作为令牌管理的参考:
async function main(auth) {
const drive = google.drive({ version: "v3", auth });
const fileList = [];
let NextPageToken = "";
do {
const params = {
// q: "", // 在这种情况下,这是不必要的。
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.log(fileList.length); // 您可以在这里看到文件的数量。
}
作为一则附注,请记住 nextPageTokens 的生命周期很短,根据我的经验和其他 Stackoverflow 用户的说法(例如 Linda Lawton - DaImTo ),它们只持续约一个小时。
参考:
英文:
Testing the overall logic of what you are trying to achieve, the recommended approach is indeed saving the nextPageToken in an array so it can be called later. In theory, just using an array.push() should suffice, this will also allow you to navigate the array index since you’ll know for sure the new ‘nextPageToken’ will be added at the end of the array.
I can recommend reviewing Tanaike’s answer in this post to use as a reference for the token management:
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.log(fileList.length); // You can see the number of files here.
}
As a side note, keep in mind that the nextPageTokens are short-lived, according to my experience and other Stackoverflow users (like Linda Lawton - DaImTo ), they last about an hour
References:
答案2
得分: 1
这是您提供的代码的翻译部分:
所以我终于成功解决了这个问题,所以我将发布一个答案,也许有人会觉得有帮助。首先,我使用数组来存储每一页的当前页面令牌。在单击“上一页”按钮时,我移除数组中的最后一个元素。以下是代码:
// 如果存在 previousPageToken,则添加“上一页”按钮
var previousPageToken = pageTokens[pageTokens.length - 1];
if (pageTokens.length != 0)
{
if (previousPageToken) {
const previousPageButton = document.createElement('button');
previousPageButton.textContent = '上一页';
previousPageButton.classList.add('btn', 'btn-primary', 'previous-page-button');
previousPageButton.addEventListener('click', function () {
pageTokens = pageTokens.slice(0, -1);
listFiles(folderId, previousPageToken); // 使用 previousPageToken 调用 listFiles()
});
document.getElementById('content').appendChild(previousPageButton);
}
else if (previousPageToken == null) {
const previousPageButton = document.createElement('button');
previousPageButton.textContent = '上一页';
previousPageButton.classList.add('btn', 'btn-primary', 'previous-page-button');
previousPageButton.addEventListener('click', function () {
pageTokens = [];
listFiles(folderId); // 调用 listFiles(),不带页面令牌
});
document.getElementById('content').appendChild(previousPageButton);
}
}
// 如果存在 nextPageToken,则添加“下一页”按钮
const nextPageToken = response.result.nextPageToken;
if (nextPageToken) {
const nextPageButton = document.createElement('button');
nextPageButton.textContent = '下一页';
nextPageButton.classList.add('btn', 'btn-primary', 'next-page-button');
nextPageButton.addEventListener('click', function () {
pageTokens.push(pageToken);
listFiles(folderId, nextPageToken); // 使用 nextPageToken 调用 listFiles()
});
document.getElementById('content').appendChild(nextPageButton);
}
然后我意识到,由于某种原因,我无法获取第一页的页面令牌(它存储为数组中的 null)。因此,我为数组中的最后一个元素为 null 的情况创建了一个单独的“else if”分支,这意味着它是第二页。因此,当我在不带页面令牌的情况下调用我的函数时,默认加载第一页。我还添加了一个检查if (pageTokens.length != 0)
,以便在第一页时不会呈现“上一页”按钮。
英文:
So I finally managed to solve this problem, so I'll post an answer, maybe someone will find it helpful. First of all, I used array to store current page token, on every page. On "Previous Page" button click, I remove the last element in array. Here's the code:
// 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);
}
Then I've realised, that I can't get first page token for some reason (it was stored as null in array). So I made seperate else if
for the case then last element in array is null
that meant it was 2nd page. So when I call my function without page token, which on default loads first page. I also made a check if (pageTokens.length != 0)
so "Previous Page" button won't render if it is first page.
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论