2015-03-31 11 views
7

Ho un Iterable e mi piacerebbe convertirlo in un flusso. Qual è la più efficiente/più breve quantità di codice per fare ciò?Qual è il modo migliore/più breve per convertire un Iterable in uno Stream, in Dart?

Ad esempio:

Future convert(thing) { 
    return someAsyncOperation(thing); 
} 

Stream doStuff(Iterable things) { 
    return things 
    .map((t) async => await convert(t)) // this isn't exactly what I want 
             // because this returns the Future 
             // and not the value 
    .where((value) => value != null) 
    .toStream(); // this doesn't exist... 
} 

Nota: iterable.toStream() non esiste, ma voglio qualcosa di simile. :)

+1

Il '.dove (...)' parte non può lavorare a causa di una funzione asincrona (chiusura passata a ' .map (...) ') restituisce sempre un futuro e quindi il confronto in' .where (...) 'sempre vero anche quando' thing' è 'null'. –

risposta

6

Ecco un semplice esempio:

var data = [1,2,3,4,5]; // some sample data 
var stream = new Stream.fromIterable(data); 

Utilizzando il codice:

Future convert(thing) { 
    return someAsyncOperation(thing); 
} 

Stream doStuff(Iterable things) { 
    return new Stream.fromIterable(things 
    .map((t) async => await convert(t)) 
    .where((value) => value != null)); 
} 
+0

Questo non restituisce un flusso di futuri invece dei valori stessi? – Fox32

+0

Sì, ma lo sarebbe anche l'esempio originale originale di Seth se esistesse l'ipotetico metodo 'toStream'. Non avevo idea se quello fosse il suo intento, ma alla fine la domanda era il modo migliore per convertire un 'Iterable' in un 'Stream'. –

3

Nel caso in cui si utilizza la versione Dart SDK 1.9 o una più recente, si potrebbe facilmente creare un flusso utilizzando async *

import 'dart:async'; 

Future convert(thing) { 
    return new Future.value(thing); 
} 

Stream doStuff(Iterable things) async* { 
    for (var t in things) { 
    var r = await convert(t); 

    if (r != null) { 
     yield r; 
    } 
    } 
} 

void main() { 
    doStuff([1, 2, 3, null, 4, 5]).listen(print); 
} 

Forse è più facile ri annuncio in quanto ha meno parentesi e metodi "speciali", ma è una questione di gusti.

+0

questo è quello che ho finito per fare. Grazie! –

1

Se si desidera sequenza processo di ciascun elemento nella iterabile è possibile utilizzare Stream.asyncMap:

Future convert(thing) { 
    return waitForIt(thing); // async operation 
} 

f() { 
    var data = [1,2,3,4,5]; 
    new Stream.fromIterable(data) 
    .asyncMap(convert) 
    .where((value) => value != null)) 
}