Javascript, HTML, CSS e... !
0 commenti

Gestire in modo sincrono le funzioni asincrone

Utilizzare Promise per sincronizzare le funzioni in Google Apps Script

Scrivendo codice per la realizzazione delle nostre app ci imbattiamo spesso in situazioni in cui abbiamo bisogno di invocare diverse funzioni con l'esigenza che queste seguano un ordine specifico, es: f1 -> f2 -> f3 ... fn, ovvero che la successiva necessiti che la precedente le fornisca un risultato prima di poter essere eseguita.

Invocando le funzioni normalmente in modo distinto e ordinato, nel caso di chiamate asincrone, non sempre è garantito il successo dell'operazione. L'approccio più semplice da utilizzare in Javascript è quello delle callback, ovvero annidando la successiva funzione all'interno della callback della funzione precedente così da garantirsi che la stessa venga eseguita nel momento in cui la precedente ha completato le relative operazioni.
Un esempio di quanto appena esposto (al solo scopo illustrativo) è il seguente:

funzione1(function() {
    console.log("fatto1");
    funzione2(function() {
        console.log("fatto2");
        funzione3(function() {
            console.log("fatto3");
            funzioneTotale(function() {
                console.log("Tutte le funzioni sono state eseguite secondo l'ordine richiesto!");
            })
        })
    })
});

Quello che ne emerge è il cosidetto callback hell, ossia è un codice poco chiaro e di difficile manutenzione (soprattutto al crescere del numero delle funzioni annidate e delle relative operazioni), è preferibile pertanto trovare una strada alternativa, ed ecco che ci vengono incontro le promise.

Una promise è un'operazione che, come dice il nome stesso, 'promette' di restituire un valore in futuro.
Lato tecnico per creare una promise è necessario l'uso del comando new Promise che richiede una funzione da eseguire che accetti due parametri: resolve e reject. Il primo verrà utilizzato in caso di successo, il secondo in caso di errore.

L'esempio seguente mostra il funzionamento di una promise in Javascript:

let funzione1 = function(){
    return new Promise(function(resolve,reject){
        resolve(console.log("fatto1"));
    });
}
let funzione2 = function(){
    return new Promise(function(resolve,reject){
        resolve(console.log("fatto2"));
    });
}
let funzione3 = function(){
    return new Promise(function(resolve,reject){
        resolve(console.log("fatto3"));
    });
}
let funzioneTotale = function(){
    funzione1()
    .then(funzione2)
    .then(funzione3)
    .then(function(){
    console.log("Tutte le funzioni sono state eseguite secondo l'ordine richiesto!");
});
}

funzioneTotale();

Come evidenzia il codice di cui sopra, una promise prevede una funzione then() che sarà eseguita al completamento della promise (chiamata in precedenza) in modo da assicurare la sequenzialità delle operazioni.

In Google Apps Script le chiamate asincrone da un client HtmlService verso il server vengono effettuate usando google.script.run, l'esempio seguente mostra come utilizzare Promise per effettuare un'operazione asincrona (nel caso specifico recuperare il numero di mail nella propria casella di posta per poi mostrarne il valore all'interno di un div definito. L'esempio è banale ma l'obiettivo è mostrarne il concetto che ne sta alla base):

Codice .gs

function doGet() {
  return HtmlService.createHtmlOutputFromFile('index'); 
}

function recuperaThreadsDaGmail() {
  var threads = GmailApp.getInboxThreads();
  return threads.length;
}

Codice .html

<!DOCTYPE html>
<html>
  <head>
     <base target="_top">
  </head>
  <body>
    <button id='button1'>Mostra il numero di Threads</button>
    <div id='text1'></div>
  </body>
  <script>
    function getThreads() {
        var p=new Promise(function(resolve, reject) {
            google.script.run.withSuccessHandler(
                function(res) {
                    resolve(res);
                }).recuperaThreadsDaGmail();
        }); 
    return p;
    }

    button1.addEventListener('click',
        function(event) {
            getThreads().then(function(res) {
                text1.innerHTML=res.toString();
            });
    });
  </script>
</html>

Dalle righe di codice di cui sopra è possibile notare che al click sul bottone viene eseguita la funzione 'getThreads().then(...', dove in getThreads() viene creata una promise, che effettua una chiamata lato server con google.script.run, al fine di attenderne il risultato per poi, then, mostrarlo a video.

E' proprio il caso di dirlo... promessa mantenuta!

Per gli amanti di jQuery ho creato un apposito tutorial che, basandosi sullo stesso esempio appena visto, mostra come utilizzare le promise avvalendosi della famosa libreria Javascript: Utilizzare jQuery e Promise in Google Apps Script.

Tags

Michele Pisani

Michele Pisani

Sviluppatore Javascript ed esperto in Digital Analytics

L'esperienza nel settore Digital Analytics unita ad anni di sviluppo in Javascript ha trovato la massima espressione in Google Apps Script che mi ha permesso, con estrema facilità e poche righe di codice, di realizzare potenti applicazioni interattive e processi automatizzati integrati con i prodotti della G Suite.

Come contattarmi
scrivi un commento

0 Commenti

Non ci sono commenti

Nessuno ha ancora commentato questo articolo, fallo tu per primo!

scrivi un commento

Scrivi un commento

Il tuo indirizzo email non sarà pubblicato.I campi contrassegnati da un * sono obbligatori
Puoi utilizzare i seguenti tag nei commenti:
[bold]testo[/bold] se vuoi evidenziare un testo con il grassetto[code]function helloworld() { }[/code] se vuoi pubblicare una porzione di codice[url]http://www.appsscript.it[/url] se devi riferirti ad un indirizzo web