Dart: la libreria js

Di - 30 January 2013 - in

Nell’articolo di oggi vedremo alcuni esempi della libreria js (ex js-interop), che definisce funzioni per l’esecuzione di codice javascript nativo nelle applicazioni Dart.

Prima di cominciare c’è una comunicazione molto importante da fare: il bootstrap file per l’esecuzione di codice Dart compilato in js, dart.js, è ora contenuto nel package browser ed è stato rimosso dal repository su https://dart.googlecode.com.

Per utilizzare dart.js si dovrà includere nella propria applicazione il package browser nel file pubspec.yaml:

dependencies:
    browser: any

e aggiungere questo script nel file HTML:

<script src="packages/browser/dart.js"></script>

Le applicazioni alle quali non verranno apportate queste modifiche smetteranno di funzionare, in quanto il file dart.js sarà rimosso dal repository. Per maggiori informazioni si consulti l’articolo originale su news.dartlang.org

Passiamo alla libreria js; per utilizzare questa libreria dobbiamo innanzitutto importarla nel nostro progetto, in pubspec.yaml:

dependencies:
  js:
    hosted: js

e nel file Dart:

import 'package:js/js.dart' as js;

Al fine di ottimizzare la gestione della memoria, il codice javascript deve essere eseguito all’interno di un determinato scope:

  js.scoped(() {
    js.context.alert('Saluti da Javascript');
  });

In caso contrario si otterrebbe un errore del tipo:

Exception: Cannot get JavaScript context out of scope.

Nell’esempio precedente js.context rappresenta una istanza di js.Proxy che mette in comunicazione Dart e Javascript.

È possibile usare le funzioni map() e array() per creare mappe e arrays da Dart a Javascript:

var options = js.map({
    'zoom': 9,
    'mapTypeId': googlemaps.MapTypeId.ROADMAP,
    'center': new js.Proxy(googlemaps.LatLng, 47.6097, -122.3331)
    });

Un altra classe fondamentale della libreria js è Callback; questa ci consente di istanziare una classe di js.Proxy che gestisca il responso di una richiesta ad un determinato servizio web via API. Esistono due tipi di Callback, once e many: il primo definisce che la funzione di callback è accessibile una sola volta, dopodichè la funzione viene mandata al garbage collector e distrutta, cosa che invece non accade per il secondo tipo di Callback.

Nell’esempio seguente utilizzeremo l’API di Discogs.com per effettuare una ricerca nel database e gestire i risultati con Dart:

import 'dart:html';
import 'package:js/js.dart' as js;

void main() {

  var script = new ScriptElement();
  script.src  = "http://api.discogs.com/database/search?q=Van+Der+Graaf+Generator+Pawn+Hearts&page=1&per_page=5&callback=dartCallback";
  document.body.nodes.add(script);

  js.scoped(() {
    js.context.dartCallback = new js.Callback.once(funzioneDart);
  });

}

void funzioneDart(response){
  var data = response.data.results;

  for(var i=0; i<data.length; i++){
    print("ID: ${data[i].id}");
    print("Titolo: ${data[i].title}");
    print("URL: http://discogs.com${data[i].uri}\n");
  }

}

Come prima cosa dobbiamo “inviare” la richiesta a discogs; questo avviene costruendo un elemento HTML script che ha come origine:

http://api.discogs.com/database/search

al quale aggiungiamo questi parametri:

  • q: la query di ricerca
  • page: il numero di pagina
  • per_page: il limite di risultati per pagina da recuperare
  • callback: la funzione javascript alla quale passare il responso

Dopodichè creiamo il proxy:

  js.scoped(() {
    js.context.dartCallback = new js.Callback.once(funzioneDart);
  });

È importante notare che, nel codice precedente, dartCallback è una funzione javascript, mentre funzioneDart è una funzione Dart. Grazie al nostro proxy, quando javascript invocherà la funzione dartCallback sarà eseguita la funzione funzioneDart.

funzioneDart() prende in ingresso response, ovvero il responso della richiesta, e mostra alcune delle informazioni recuperate. L’output del programma è:

ID: 33426
Titolo: Van Der Graaf Generator - Pawn Hearts
URL: http://discogs.com/Van-Der-Graaf-Generator-Pawn-Hearts/master/33426

ID: 467504
Titolo: Van Der Graaf Generator - Pawn Hearts
URL: http://discogs.com/Van-Der-Graaf-Generator-Pawn-Hearts/release/467504

ID: 540746
Titolo: Van Der Graaf Generator - Pawn Hearts
URL: http://discogs.com/Van-Der-Graaf-Generator-Pawn-Hearts/release/540746

ID: 768504
Titolo: Van Der Graaf Generator - Pawn Hearts
URL: http://discogs.com/Van-Der-Graaf-Generator-Pawn-Hearts/release/768504

ID: 1399604
Titolo: Van Der Graaf Generator - Pawn Hearts
URL: http://discogs.com/Van-Der-Graaf-Generator-Pawn-Hearts/release/1399604

Avendo definito dartCallback come Callback.once, se si provasse ad accedere una seconda volta a dartCallback il programma terminerebbe con un errore.

Sebbene nella maggior parte dei casi sia sufficiente un Callback di tipo once, per alcuni servizi, in particolare quelli che richiedono una autenticazione, è necessario che una funzione resti disponibile anche dopo il primo accesso. Un Callback di tipo many si istanzia allo stesso modo di once:

js.context.auth = new js.Callback.many((){
  js.context.gapi.client.setApiKey('API_KEY');
  js.context.window.setTimeout(
    js.context.gapi.auth.authorize(js.map({
    'client_id':CLIENT_ID,
    'scope':SCOPE,
    'immediate':immediate
    }),
    js.context.onAuthResponse), 1
  );
});

L’esempio precedente è tratto da un’applicazione di prova che attraverso l’API di Google+ recupera e mostra alcune informazioni dell’utente corrente. Il tutorial si trova su claudiodangelis.it mentre il codice sorgente è su GitHub,

Il codice di esempio utilizzato in questo articolo è disponibile sull’account Engeene su GitHub

Leave a Reply

Claudio d'Angelis Articolo scritto da

Programmatore e studente di Informatica, appassionato di musica, web e sistemi UNIX. Collabora con Googlab dall'Ottobre 2012.

Contatta l'autore

Previous post:

Next post: