1

当外部循环的迭代次数少于大约 1 次时,以下脚本将按预期运行。100 次。如果外部循环迭代几千次,我可以看到我的 console.log 被混淆了。例如:

  • 3x 外环输出
  • 1x 内环输出
  • 1x 外循环输出 // 不应该发生,因为所有外循环输出都在内循环输出之前!

...或者...

  • 3x 外环输出
  • 2x 内循环输出 // 不应该发生,因为只有一个内循环输出!

...还有许多其他奇怪的组合,但我认为它总是相同的原因。

在我的情况下,async/await 和 do/while 循环的组合似乎并不顺利。我试图通过制作单独的递归函数来摆脱 do/while 循环,但徒劳无功。还有另一种方法吗?非常感谢任何帮助。

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
  });
}

编辑:

  • 根据要求,请在原始代码下方找到。
  • 我认为您需要创建一个新的谷歌开发者控制台项目并插入相应的“clientId”和“apiKey”。
  • 同时,我用递归函数调用交换了外部 do/while 循环,但输出仍然很奇怪。
  • 我不确定如何包含 browser.js 和 runtime.js,因此脚本标签仍然包含我的路径。
  • 另外,我不确定这是否在片段中起作用: type="text/babel" src="js/driverights.js" 在第四个脚本标签中。

"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>

4

1 回答 1

1

我没有在您的asyncGenerator函数中看到嵌套的 do-while 循环,但我确实看到asyncGenerator可以递归调用(有时是间接调用),并且在每次调用期间都会await发生一些新的 asynchronous 。不能保证这些await表达式中的任何一个都将以相同的顺序完成,因此不能保证console.log语句总是按照它们在代码中发生的顺序。你的一些await表达依赖于网络(fe await listFiles(...)),而网络并不是一直都那么可预测的。首先开始的请求可能不会首先完成,因此您的递归函数调用不会总是按预期执行。

为了解决这个问题,您可以做的一件事是将递归调用重构为也使用await,因此递归调用可能如下所示:

await asyncGenerator(fileList.result.nextPageToken);
于 2015-11-25T07:10:05.260 回答