Die Google Apps Script-Web-App wird nicht wie erwartet asynchron ausgeführt
Ich habe eine nicht blockierende Web-App (dh kein LockService), die einen in ScriptProperties gespeicherten Zähler zurückgibt.
Ich habe einen künstlichen Schlaf im Skript, um asynchrone Aufrufe der Web-App zu testen.
Wenn ich mir diesen Code unten anschaue, würde ich davon ausgehen, dass zwei aufeinanderfolgende Aufrufe der Web-App dieselbe Nummer zurückgeben sollten.
Dies ist jedoch nicht der Fall. Zwei Aufrufe der Web-App direkt nacheinander geben steigende Nummern zurück. Dies lässt mich denken, dass der erste Anruf beendet wird, bevor der zweite ausgeführt wird - was keinen Sinn ergibt.
function doGet(e)
{
// get script properties
var scriptProperties = PropertiesService.getScriptProperties();
// get ID
var id = parseInt(scriptProperties.getProperty("id"));
// fake a long process
// enough time to make another call to the web-app
// in theory, the second call will get the same value for `id`
Utilities.sleep(5000);
// write a new value
scriptProperties.setProperty("id", id + 1);
// return it
return ContentService.createTextOutput(id);
}
Ich versuche herauszufinden, wie / warum. Unterstützt Google keine asynchronen Anrufe für Web-Apps?
Sie können dies bei sehen https://script.google.com/macros/s/AKfycbxP6TQeMv_4b1lsYvGLA3YAn_reBhZ64Y2d04DotQ4CFJQtKhM/exec.
** UPDATE **
Hier ist eine lokale HTML-Datei, die ich zum Testen verwende.
<!DOCTYPE html>
<html>
<head>
<base target="_top">
<script type="text/javascript">
function doIt()
{
console.log("doIt: start");
setTimeout(callIt, 500);
console.log("doIt: end");
}
function callIt()
{
console.log("callIt: start");
var request = new XMLHttpRequest();
request.open('GET', 'https://script.google.com/macros/s/AKfycbxP6TQeMv_4b1lsYvGLA3YAn_reBhZ64Y2d04DotQ4CFJQtKhM/exec', true);
request.onload = function()
{
if(this.status >= 200 && this.status < 400)
{
document.querySelector("#output").innerText += this.response + ", ";
}
else
{
alert("error");
}
};
request.onerror = function()
{
alert("error");
};
request.send();
console.log("callIt: end");
}
</script>
</head>
<body>
output:
<div id="output"></div>
<input type="button" value="Click me" onclick="doIt()">
</body>
</html>
Wenn Sie sehr schnell auf die Schaltfläche klicken, wird dieselbe Nummer zurückgegeben, aber nicht ...
Antworten
Ja! Webanwendungsaufrufe werden gerne doPost()asynchron ausgeführt.
Problem:
Der Grund, warum Sie die Kollision nicht replizieren konnten, ist, dass Ihre sleepZeit im Vergleich zu der Zeit, die der Browser für http-Aufrufe benötigt, zu niedrig war
Lösung:
Erhöhen Sie
sleepauf 1 Minute oder mehr.Utilities.sleep(1*60*1000);Sie können Asynchronität auch leicht nachweisen, wenn Sie eine zufällige Ruhezeit mit dem folgenden Snippet-Skript verwenden, das die Zeit jeder Schleife zusätzlich zu zufälligen "callIt-Enden" anzeigt.
Utilities.sleep(Math.floor(Math.random()*60000)+1);
/*<ignore>*/console.config({maximize:true,timeStamps:false,autoScroll:true});/*</ignore>*/
function callIt(i) {
const label = 'callIt' + i;
console.log(label + ' start');
console.time(label);
const request = new XMLHttpRequest();
request.open(
'GET',
'https://script.google.com/macros/s/AKfycbxP6TQeMv_4b1lsYvGLA3YAn_reBhZ64Y2d04DotQ4CFJQtKhM/exec',
true
);
request.onload = function() {
if (this.status >= 200 && this.status < 400) {
console.log(this.response + `- ${label}`);
console.log(label + ' end');
console.timeEnd(label);
console.log('\n')
} else {
alert('error');
}
};
request.onerror = function() {
alert('error');
};
request.send();
}
let i = 0;
while (++i < 10) callIt(i);
<!-- https://meta.stackoverflow.com/a/375985/ --> <script src="https://gh-canon.github.io/stack-snippet-console/console.min.js"></script>