L'application Web Google Apps Script ne s'exécute pas de manière asynchrone comme prévu
J'ai une application Web non bloquante (c'est-à-dire pas de LockService) qui renvoie un compteur stocké dans ScriptProperties.
J'ai un sommeil artificiel dans le script pour tester les appels asynchrones à l'application Web.
En regardant ce code ci-dessous, je suppose que deux appels successifs à l'application Web devraient renvoyer le même numéro.
Cependant, ce n'est pas le cas. Deux appels à l'application Web, l'un après l'autre, renvoient des nombres croissants. Cela me fait penser que le premier appel se termine avant le second, ce qui n'a pas de sens.
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);
}
J'essaye de comprendre comment / pourquoi. Google ne prend-il pas en charge les appels asynchrones pour les applications Web?
Vous pouvez le voir s'exécuter à https://script.google.com/macros/s/AKfycbxP6TQeMv_4b1lsYvGLA3YAn_reBhZ64Y2d04DotQ4CFJQtKhM/exec.
** METTRE À JOUR **
Voici un fichier HTML local que j'utilise pour tester.
<!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>
Cliquer sur le bouton très rapidement devrait renvoyer le même numéro, mais ce n'est pas le cas ...
Réponses
Oui! Les applications Web appellent comme doPost()s'exécuter de manière asynchrone.
Problème:
La raison pour laquelle vous n'avez pas pu répliquer la collision est que votre sleeptemps était trop court par rapport au temps pris par le navigateur pour effectuer des appels http
Solution:
Augmentez
sleepà 1 minute ou plus.Utilities.sleep(1*60*1000);Vous pouvez aussi facilement prouver l'asynchronisme, si vous utilisez un temps de sommeil aléatoire avec le script d'extrait ci-dessous, qui affichera l'heure de chaque boucle en plus des "callIt end" aléatoires.
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>