Nell'articolo precedente abbiamo parlato in generale dell'uso delle Promise
e della coppia async/await
. Purtroppo ExtJS il supporto è limitato alle chiamate AJAX. Sarebbe molto interessante poter utilizzare questo tipo di sintassi anche per le letture/scritture sugli store ma anche sui modelli o per ottenere il risultato da una dialogbox.
Store
Gli store
sono una delle classi più usate in ExtJS. Se l'unico scopo è visualizzare i dati da su una lista o una griglia non ci sono problemi, ma nel caso in cui si vogliano elaborare i dati una volta letti è necessarrio utlizzare una callback in questo modo:
store.load({
scope: this,
callback: function(records, operation, success) {
// the operation object
// contains all of the details of the load operation
console.log(records);
}
});
ExtJS fortunatamente ci dà la possibilità di modificare a piacimento anche classi esistenti tramite l'utilizzo di override
. Possiamo quindi modificare il metodo load
aggiungendo una configurazione, per esempio usePromise
, che trasformi il valore di ritorno di store.load
in una promise, in modo da poterla chiamare con await
.
Ext.define('Fiddle.overrides.Store', {
override: 'Ext.data.ProxyStore',
load(options) {
let me = this;
if (options && options.usePromise) {
delete options.usePromise;
return new Ext.Promise(function (resolve, reject) {
me.load(Ext.apply(options || {}, {
callback(records, operation, success) {
if (success) {
resolve(records);
} else {
reject(operation);
}
}
}));
});
} else {
return this.callParent(arguments);
}
}
});
In questo modo possiamo trasformare il codice precedente così:
const records = await store.load({ usePromise: true });
console.log(records);
L'unica accortezza è che la funzione dove sarà inserito quel codice dovrà essere dichiarata come async
.
Dialog box
Con ExtJS anche il risultato di una semplice dialog box richiede una callback:
Ext.Msg.confirm('Info', 'Do you want to save changes?', function (buttonId) {
if (buttonId === 'yes') {
//...
}
});
In questo caso probabilmente invece che usare un override ha più senso creare una nuova classe singleton
:
Ext.define('Fiddle.Message', {
singleton: true,
confirm(message) {
var me = this;
return new Ext.Promise(function (resolve, reject) {
Ext.Msg.confirm(document.title, message, function(buttonId) {
resolve(buttonId);
});
});
}
});
Notate che non è stato necessario usare il metodo reject
della promise in quanto la dialog box non ha una condizione di errore.
In questo modo il codice precedente diventa questo:
const buttonId = await Fiddle.Message.confirm('Do you want to save changes?');
if (buttonId === 'yes') {
//...
}
Conclusione
Usando una struttura simile si può aggiungere il supporto alle promise e async/await dovunque sia necessario rendendo il codice sicuramente più leggibile.
Potete provare gli esempi dell'articolo su questo fiddle.