Dart: Funzioni asincrone ed oggetti Futures

Di - 19 January 2013 - in

Abbiamo concluso l’articolo precedente introducendo la classe Future, ovvero una classe che rappresenta un oggetto necessario per ottenere valori non ancora disponibili nel momento in cui viene invocato.

Nel caso specifico dell’articolo precedente abbiamo visto che un oggetto Future viene restituito dal metodo SendPort.call():

import 'dart:isolate';

saluti() {
  . . .
}

main() {
  . . .
  sPort.call(['Ciao','Hello','Hola']).then((messaggio){
    if(messaggio=="ok") {
      print('Messaggio ricevuto, main() può ora terminare');
    }
  });
. . .
}

Il metodo then() è un membro di Future e viene invocato quando quest’ultimo è completo, in questo caso quando l’isolate saluti() “risponde” con un messaggio.

Gli oggetti Future sono dunque necessari per l’esecuzione asincrona delle funzioni di un programma. Prendiamo ad esempio questo programma che legge se stesso e stampa il contenuto:

import 'dart:io';

main() {
  print('Inizio');
  var options = new Options();
  var file = new File(options.script);
  Future<String> finishedReading = file.readAsString(Encoding.ASCII);
  finishedReading.then((text) => print(text));
  print('Fine');
}

Il metodo readAsString restituisce un Future identificato da finishedReading; quando la lettura del file è stata completata, then() stampa il valore di text. (questo esempio, al quale abbiamo apportato delle modifiche, è disponibile sul sito ufficiale)

Eseguendo il programma notiamo che il testo viene stampato dopo il comando print('Fine') poichè la lettura del testo avviene in modo asincrono. Esistono tuttavia dei metodi sostitutivi che “forzano” l’esecuzione sincrona delle istruzioni, come ad esempio readAsStringSync():

import 'dart:io';

main() {
  print('Inizio');
  var options = new Options();
  var file = new File(options.script);
  var testo = file.readAsStringSync(Encoding.ASCII);
  print(testo);
  print('Fine');
}

Si può vedere che in questo programma non viene gestito nessun oggetto Future in quanto ogni istruzione viene eseguita solo al completamento della precedente. Anche writeAsString, metodo che scrive una stringa in un file, esiste in entrambe le versioni async e sync:

  1. async:
    import 'dart:io';
    
    main() {
      print('Inizio');
      File mioFile = new File('mioFile.txt');
      mioFile.createSync();
      String testo = "Lorem ipsum";
      Future<File> futuro = mioFile.writeAsString(testo);
      futuro.then((_){
        print('Ho finito di scrivere');
      });
      print('Fine');
    }
  2. sync:
    import 'dart:io';
    
    main() {
      print('Inizio');
      File mioFile = new File('mioFile.txt');
      mioFile.createSync();
      String testo = "Lorem ipsum";
      mioFile.writeAsStringSync(testo);
      print('Ho finito di scrivere');
      print('Fine');
    }

Se nel nostro programma stiamo usando una funzione la cui esecuzione impiega un tempo relativamente lungo possiamo renderla asincrona utilizzando il metodo future di un’istanza di Completer. Analizziamo questo programma:

main(){
  Future<String> future = funzioneLenta();
  future.then((msg){
    print('Ho ricevuto: $msg');
    });
}

Future<String> funzioneLenta(){
  Completer<String> completer = new Completer<String>();
  String valoreDiRitorno = 'valore';
  completer.complete(valoreDiRitorno);
  return completer.future;
}
  • Future<String> future = funzioneLenta();Avvia funzioneLenta() e aspetta di ricevere un’istanza di Future
  • Completer<String> completer = new Completer<String>();Istanziamo un oggetto Completer tale da contenere un dato di tipo String
  • completer.complete(valoreDiRitorno)definisce il valore da passare al metodo then() una volta che la funzione sarà completa
  • return completer.future;restituisce una istanza di Future

Con questo articolo termina la panoramica delle librerie e classi basilari. Nel prossimo articolo ci occuperemo della libreria js-interop, che ci permette di utilizzare codice Javascript in Dart.

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: