The following script runs as expected when the outer loop iterates less than approx. 100 times. If the outer loop iterates a few thousand times, I can see that my console.log s are mixed up. For instance:
...or...
...there are many other weird combinations, but I think it is always the same cause.
It seems that the combination of async/await and do/while loops do not work smoothly in my case. I have tried to get rid of the do/while loops by making separate recursive functions, but in vain. Is there another way of doing that? Any help is very appreciated.
async function asyncGenerator() {
// other code
do {
// other code
var fileList = await listFiles(nextPageToken);
// other code
do {
// other code
var parents = await requestParents(fileList.result.items[0].parents[0].id);
// other code
} while (response.result.parents[0].isRoot === false);
// other code
} while (fileList.result.nextPageToken !== "undefined")
// other code
}
function listFiles(token) {
return gapi.client.drive.files.list({
'maxResults': sizeResults,
'pageToken': token,
'q': query
});
}
function requestParents(fileId) {
return gapi.client.drive.files.get({
'fileId': fileId
});
}
EDIT:
"use strict"; var driveRights = (function() { var clientId = 'YOUR CLIENT ID'; var apiKey = 'YOUR API KEY'; var scopes = 'https://www.googleapis.com/auth/drive https://www.googleapis.com/auth/drive.readonly https://www.googleapis.com/auth/drive.appfolder https://www.googleapis.com/auth/drive.apps.readonly https://www.googleapis.com/auth/drive.file https://www.googleapis.com/auth/drive.install https://www.googleapis.com/auth/drive.metadata https://www.googleapis.com/auth/drive.metadata.readonly https://www.googleapis.com/auth/drive.photos.readonly https://www.googleapis.com/auth/drive.scripts'; function handleClientLoad() { var initButton = document.getElementById('init'); initButton.onclick = function() { gapi.client.setApiKey(apiKey); window.setTimeout(checkAuth(false, handleAuthResult), 1); } } function checkAuth(imm, callback) { gapi.auth.authorize({ client_id: clientId, scope: scopes, immediate: imm }, callback); } function handleAuthResult(authResult) { if (authResult) { gapi.client.load('drive', 'v2', initialize); } else { $('#progress').html('Anmeldung fehlgeschlagen'); } } ///////////////////////////////////////////////////////////////////////////////////////////////////// var timeOut = 120; var counter = 0; var tokenMemory; var start = new Date().getTime(); var currentTime; // Test data var sizeResults = 1; var parentFolders = ['0B11RmPttIhB3aFhaMzFQQ0Rjbm8', '0B6R9YDOGf_BUSC0wNW1lRWlnSmc', '0B6R9YDOGf_BUUHRoUW9tRkljUFk', '0B6R9YDOGf_BUfjc3QlZ1YU9Tb2lHcmhLVGhWc3FqSzE4S1dvZlhlLWd6aVFhUWdENWkyYkU']; var newUser = 'TEST@TEST.COM'; var query = 'trashed = false'; var initialize = function() { $('#start').click(function() { asyncGenerator(); }); }; async function asyncGenerator(token) { try { // REQUEST FILES counter += sizeResults; tokenMemory = token; await sleep(timeOut); var fileList = await listFiles(token); console.log("Requested so far: ", counter); console.log("Number of received files: ", fileList.result.items.length); console.log(fileList); // END REACHED if (fileList.result.items.length === 0) { console.log("DONE - no more files"); return; } // CHECK FILES var firstCheckResult = firstCheck(fileList.result.items[0]); // Rights if (firstCheckResult === "rights") { $('#progress').append(`Rechte | ${fileList.result.items[0].title} | ${fileList.result.items[0].owners[0].displayName} | ${fileList.result.items[0].alternateLink} <br>`); console.log("TO DO: rights"); } // Check parents if (firstCheckResult === "checkParents") { var parentID = fileList.result.items[0].parents[0].id; do { console.log("Do while loop parents are not root"); await sleep(timeOut); var response = await requestParents(parentID); parentID = response.result.parents[0].id; } while (response.result.parents[0].isRoot === false); var secondCheckResult = secondCheck(response); } // No change if (firstCheckResult === "notChange" || secondCheckResult === "notChange") { console.log("TO DO: not"); } // Change if (firstCheckResult === "change" || secondCheckResult === "change") { console.log("TO DO: change"); await sleep(timeOut); await requestPermissions(fileList.result.items[0].id); } // REFRESH TOKEN IF NECESSARY currentTime = new Date().getTime(); if (currentTime > (start + 2700000)) { start = new Date().getTime(); console.log("Restart asyncGenerator! Reason: Create new token"); checkAuth(true, asyncGenerator); } // CHECK IF NEXT PAGE TOKEN EXISTS if (typeof fileList.result.nextPageToken !== "undefined") { asyncGenerator(fileList.result.nextPageToken); } else { console.log("DONE - no next page token"); } // RESTART IF ERROR OCCURS } catch (err) { console.log(err); if (err.result.error.code === 500) { console.log("Restart asyncGenerator! Reason: Error 500"); asyncGenerator(tokenMemory); } if (err.result.error.message.indexOf("Es ist ein interner Fehler aufgetreten, der die Freigabe") > -1) { console.log("Restart asyncGenerator! Reason: Permission Error"); asyncGenerator(tokenMemory); } } } function listFiles(token) { return gapi.client.drive.files.list({ 'maxResults': sizeResults, 'pageToken': token, 'q': query }); } function requestParents(fileId) { return gapi.client.drive.files.get({ 'fileId': fileId }); } function requestPermissions(fileId) { return gapi.client.drive.permissions.insert({ 'fileId': fileId, 'sendNotificationEmails': false, 'resource': { 'value': newUser, 'type': 'user', 'role': 'writer', 'name': 'Team' } }); } function firstCheck(file) { // File can't be shared -> output to site if (file.writersCanShare === false) { return "rights"; } // File is forbidden folder -> do not change else if (parentFolders.indexOf(file.id) > -1) { return "notChange"; } // File is root-folder and has no parents -> do change else if (file.parents.length === 0 && parentFolders.indexOf(file.id) === -1) { return "change"; } // Parent-folder of file is root-folder and parent-folder ist not a forbidden folder -> do change else if (file.parents[0].isRoot === true && parentFolders.indexOf(file.parents[0].id) === -1) { return "change"; } // Parent-folder of file is a forbidden-folder -> do not change else if (parentFolders.indexOf(file.parents[0].id) > -1) { return "notChange"; } // If none of these exceptions is met -> check parent else { return "checkParents"; } } function secondCheck(file) { // If file's parent is one of the forbidden folders-> do not change if (parentFolders.indexOf(file.result.id) > -1) { return "notChange"; } else { return "change"; } } function sleep(ms) { return new Promise(resolve => setTimeout(resolve, ms)); } return { start: handleClientLoad, }; })(); driveRights.start();
.cover { margin: 5% 0; background: none; } .full { background: url(cover.jpg) no-repeat center center fixed; -webkit-background-size: cover; -moz-background-size: cover; -o-background-size: cover; background-size: cover; } .coverbox { background-color: rgba(255,255,255,0.8) !important; } .separator { border: 0; height: 1px; background-image: -webkit-linear-gradient(left, rgba(0,0,0,0), rgba(0,0,0,0.75), rgba(0,0,0,0)); background-image: -moz-linear-gradient(left, rgba(0,0,0,0), rgba(0,0,0,0.75), rgba(0,0,0,0)); background-image: -ms-linear-gradient(left, rgba(0,0,0,0), rgba(0,0,0,0.75), rgba(0,0,0,0)); background-image: -o-linear-gradient(left, rgba(0,0,0,0), rgba(0,0,0,0.75), rgba(0,0,0,0)); } #init, #start { width: 200px; margin-top: 10px; }
<!DOCTYPE> <html> <head> <title>Drive Rights</title> <link rel="stylesheet" href="style.css"> <link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.4/css/bootstrap.min.css"> <script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script> <script src="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.4/js/bootstrap.min.js"></script> <script type="text/javascript" src="js/browser.js"></script> <script type="text/babel" src="js/driverights.js"></script> <script type="text/javascript" src="js/runtime.js"></script> <script src="https://apis.google.com/js/client.js"></script> </head> <body class="cover full"> <div class="container"> <div class="jumbotron coverbox clearfix"> <h1>Drive Rights</h1> <p> Change file permissions for specific user. </p> <hr class="separator"> <div id="info" class="clearfix"> <p> First click login, then start. </p> <p class="text-center"> <button type="button" class="btn btn-primary btn-lg" id="init"> Login </button></br> <button type="button" class="btn btn-primary btn-lg" id="start"> Start </button> </p> </div> <div id="progress"></div> </div> </body> </html>
I don't see a nested do-while loop in your asyncGenerator
function, but I do see that asyncGenerator
can be called recursively (sometimes indirectly), and during each call some new asynchronous await
s happen. There is no guarantee that any of those await
expressions will complete in the same order, and thus no guarantee that the console.log
statements always be in order that they happen in the code. Some of your await
expressions are relying on the network (fe await listFiles(...)
) and the network isn't so predictable all the time. It's possible a request that started first might not finish first, so your recursive function calls won't always execute as expected.
One thing you can do to possibly fix this is to refactor your recursive calls to also use await
, so the recursive calls might look like:
await asyncGenerator(fileList.result.nextPageToken);
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.