Nonostante GraphQL sia una tecnologia sfruttabile con qualsiasi linguaggio di programmazione, è maturato in seno all'ambiente Javascript che resta pertanto uno dei suoi principali contesti di utilizzo. In questa lezione, affronteremo la realizzazione di un client Javascript per GraphQL sia come integrazione in applicativi Node.js sia come dotazione di pagine web. Faremo in ogni caso accesso al servizio di prova realizzato in una lezione precedente, che costituiva un database di proverbi in grado, tra l'altro, di restituirne uno casuale.
Iniziamo con alcune precisazioni:
- le soluzioni client per GraphQL sono suddivisibili in due categorie. Ci sono client pensati per il solo fetching di dati e client con cache. Nella prima tipologia rientrano tutti quei casi in cui la libreria si occupa esclusivamente di offrire metodi comodi per interagire con il servizio GraphQL. Le librerie con cache sono tipicamente soluzioni più evolute, che oltre ad offrire funzionalità di fetching permettono di conservare dati in memoria per ridurre il traffico in rete ed ottimizzare così il consumo di banda;
- librerie client per Node.js o pagine web non sono necessariamente strumenti diversi, ma spesso lo stesso framework può essere impiegato in entrambi gli ambienti.
Nel seguito offriremo indicazioni di carattere generale, ma esiste comunque un gran numero di alternative impiegabili per gli stessi compiti.
Client Node.js
Supponiamo di voler sfruttare il servizio facendo in modo che si possa passare come argomento da riga di comando il numero di proverbi casuali da richiedere: qualora questo numero non fosse indicato, ne sarà richiesto soltanto uno. Ad esempio, il nostro script - che prenderà nome clientnode.js - potrà essere invocato così:
node clientnode.js
Ciò richiederà un solo proverbio casuale. In alternativa, potremo eseguire il comando seguente:
node clientnode.js 3
Quest'ultimo richiederà tre proverbi.
Tra le varie opzioni sfruttabili, abbiamo scelto di presentare la libreria graphql-request che si caratterizza per l'uso semplice e molto diretto, ideale per il primo approccio alla tematica ma anche per impieghi professionali in casistiche non troppo complesse. Stiamo parlando di un client per il solo fetching utilizzabile anche in pagine web.
La possiamo importare con npm, seguendo le indicazioni fornite sulla pagina ufficiale del progetto:
npm install graphql-request
Il nostro esempio sarà costituito dal seguente codice:
// importazione della libreria
graphreq=require('graphql-request');
request=graphreq.request;
// definizione della query da inoltrare
const query = `query{proverbioRandom}`
// numero di default di proverbi da richiedere
quanti_proverbi=1
// verifica di eventuali argomenti da riga di comando
if (process.argv.length>2 && !isNaN(parseInt(process.argv[2])))
{
// se c'è un argomento viene interpretato per appurare quanti proverbi vanno richiesti
quanti_proverbi=parseInt(process.argv[2])
console.log("Richiesti "+quanti_proverbi+" proverbi casuali");
for (let i = 0; i < quanti_proverbi; i++) {
request('http://localhost:8888/proverbi', query).then(data =>
console.log(data.proverbioRandom))
}
}
else
{
// nessun argomento da riga di comando quindi verrà richiesto un solo proverbio
console.log("Richiesto un solo proverbio casuale");
request('http://localhost:8888/proverbi', query).then(data =>
console.log(data.proverbioRandom))}
Dopo aver importato la libreria, abbiamo definito che il numero di proverbi da richiedere per default sia 1, e questa situazione sarà quella in cui non siano passati argomenti da riga di comando. L'uso della libreria graphql-request si rivela piuttosto immediato; è infatti sufficiente:
- definire la query da inviare (potremo provarla prima in GraphiQL e poi copiarla qui);
- inoltrarla tramite request all'indirizzo specificato:
request('http://localhost:8888/proverbi', query).then(data => console.log(data.proverbioRandom))
Si noti l'uso del then
per indicare il blocco di codice da eseguire per elaborare i dati ricevuti dal servizio. Da questo punto di vista la libreria che abbiamo usato si rivela molto moderna, sfruttando le promise di Javascript e venendo incontro a tutte le esigenze del programmatore. Si noti che qualora venga passato un argomento da riga di comando non convertibile in numero, per come è stato strutturato il costrutto if...else
, verrà restituito un solo proverbio in quanto la condizione booleana risulterà falsa: tutto ciò potrebbe essere raffinato, ma per gli scopi della lezione può ritenersi sufficiente.
All'esecuzione, il funzionamento senza argomenti da riga di comando produrrà questo:
> node clientnode.js
Richiesto un solo proverbio casuale
Una mela al giorno toglie il medico di torno
Con più argomenti, riceveremo invece i seguenti dati:
> node clientnode.js 3
Richiesti 3 proverbi casuali
Battere il ferro finché è caldo
Bacco, tabacco e Venere riducon l'uomo in cenere
Ai pazzi si dà sempre ragione
Client web
Il modo più immediato per utilizzare GraphQL in una pagina web consiste nello sfruttare le Fetch API, set di funzionalità introdotte in HTML5 per agevolare l'inoltro di richieste HTTP senza integrazione di strumenti esterni. Per farne uso, basta utilizzare fetch specificando l'indirizzo da contattare per la richiesta, il metodo HTTP (nel nostro caso sarà POST
), le intestazioni e soprattutto il corpo che conterrà la query GraphQL.
Anche in questo tipo di interrogazioni si fa uso delle promise in modo da creare un flusso di elaborazioni che, sequenzialmente, elaborino i dati ottenuti a seguito della richiesta. Nell'esempio che segue, effettuiamo una richiesta al servizio che abbiamo realizzato nelle lezioni precedenti, estraendone il contenuto in JSON ed utilizzandone il campo data. A titolo di esempio,
estraiamo il risultato, riportato nel campo proverbioRandom, e lo pubblichiamo in una finestra di alert:
fetch('http://localhost:8888/proverbi', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
'Accept': 'application/json',
},
body: JSON.stringify({query: "{proverbioRandom}"})
})
.then(raw => raw.json())
.then(response =>
{
proverbio=response.data.proverbioRandom;
alert('Il proberbio di oggi è "'+proverbio+'"')
}
);
Ulteriori librerie
Quello viste sono due soluzioni comode ma non certo le uniche esistenti. Parlando di alcune alternative potremmo pensare a FetchQL, uno strumento semplice, dedicato al fetching, sfruttabile sia in un'applicazione Node.js sia nel browser: potremmo vederlo come alternativa a graphql-request. Viceversa, uno dei client più ricchi in assoluto è Apollo Client, che dispone di funzionalità di caching: è leggero, efficiente, facilmente integrabile in ogni tipo di applicazione. Come ultima nota vale la pena citare Relay, che Facebook ha elaborato come ponte tra le sue due creazioni: React e GraphQL. Offre funzionalità di cache che verranno attivate mediante un oggetto Environment.