Async/await con ExtJS

Async/await con ExtJS

Probabilmente una delle funzionalità più apprezzate delle ultime versioni di JavaScritpt sono le promise e in particolare il loro uso tramite le nuove keyword del linguaggio async/await introdotte con ECMAScript 2017.

Le promise

Per semplificarla molto le promise sono un metodo standardizzato per chiamare funzioni asincrone. In JavaScript, da sempre, l'uso di funzioni asincrone è molto comune, dalle chiamate Ajax, agli eventi e altro. ExtJS stesso ne fa un uso molto esteso. Prima delle promise l'approccio più classico prevedeva l'uso di callback:

Ext.Ajax.request({
     url: 'ajax_demo/sample.json',

     success: function(response, opts) {
         var obj = Ext.decode(response.responseText);
         console.dir(obj);
     },

     failure: function(response, opts) {
         console.log('server-side failure with status code ' + response.status);
     }
 });

In questo caso success e failure sono le due callback. Come saprà chiunque usi ExtJS o JavaScript da un po' di tempo, alla lunga questo modo di lavorare risulta estremamente complesso, specialmente quando abbiamo callback che chiamano altre callback e così via. Producendo quello che in gergo viene chiamato come callback hell:


a(function (resultFromA) {
    b(resultFromA, function (resultFromB) {
        c(resultFromB, function (resultFromC) {
            d(resultFromC, function (resultFromD) {
                e(resultFromD, function (resultFromE) {
                    f(resultFromE, function (resultFromF) {
                        console.log(resultFromF);
                    });            
                });            
            });            
        });
    });
});

A partire da ExtJS 6.0 il metodo Ext.Ajax.request restituisce una promise quindi è possibile usarlo anche in questo modo:

Ext.Ajax.request({
    url: 'ajax_demo/sample.json'
 }).then(function(response, opts) {
    var obj = Ext.decode(response.responseText);
    console.dir(obj);
 });

In questo caso la funzione request restituisce una Promise che ha un metodo then al quale passare una callback in caso di esito positivo e un metodo catch che varrà usato in caso di esito negativo. Visto così non sembra cambiare poi molto, ma le cose si fanno più interessanti quando chiamiamo più metodi asincroni uno dietro l'altro:

Ext.Ajax.request({
    url: 'ajax_demo/sample1.json'
 }).then(function(response, opts) {
    return Ext.Ajax.request({
        url: 'ajax_demo/sample2.json'
    });
 }).then(function(response, opts) {
    return Ext.Ajax.request({
        url: 'ajax_demo/sample3.json'
    });
 }).then(function(response, opts) {
    return Ext.Ajax.request({
        url: 'ajax_demo/sample4.json'
    });
 }).then(function(response, opts) {
    // ...
 });

Promises schema

In questo modo evitiamo il callaback hell e rendiamo il codice più leggibile. Usando le promise si possono gestire più facilmente più chiamate contemporanee e altri casi d'uso complessi.

Async/await

La parte più interessante viene adesso e cioè unendo le promise con le nuove keyword async/await. Infatti, se una funzione restituisce un promise può essere usata in questo modo:

async function dataReader() {
    var response = await Ext.Ajax.request({
        url: 'ajax_demo/sample.json'
    });

    var obj = Ext.decode(response.responseText);
    console.dir(obj);
}

Usando la keyword await prima della funzione, invece di ottenere una promise, l'applicazione virtualmente si ferma ed attende di avere a disposizione un valore che verrà restituito. In realtà l'applicazione non si ferma veramente (l'interfaccia rimane reattiva e altre porzioni di codice continueranno a funzionare normalmente), ma quelle specifica funzione attenderà di ricevere un valore prima di continuare.

Per approfondire trovate anche un mio video sul canale youtube di Wintech Italia dal titolo: Async/await per uscire dall’inferno delle callback e un'altro articolo su questo sito.