2015-12-17 13 views
5

Sto lavorando su un progetto che richiede modelli. Il modello principale ha un attributo di importazione che specifica l'origine dati. I dati vengono quindi letti e inseriti nella stringa utilizzando String.replaceAllMapped. Il seguente codice funziona correttamente con File api perché ha un metodo readAsStringSync per leggere il file in modo sincrono. Ora voglio leggere da qualsiasi flusso arbitrario che restituisce un futuro.String.replaceAllMapped con risultato asincrono

Come eseguire lavori asincroni/attendi in questo scenario? Ho anche cercato una sostituzione async compatibile per replaceAllMapped ma non ho trovato una soluzione che non richieda più passaggi con la regex.

Ecco un esempio molto semplificato del mio codice:

String loadImports(String content){ 
    RegExp exp = new RegExp("import=[\"\']([^\"\']*)[\"\']>\\s*<\/"); 

    return content.replaceAllMapped(exp, (match) { 
    String filePath = match.group(1); 

    File file = new File(filePath); 
    String fileContent = file.readAsStringSync(); 

    return ">$fileContent</"; 
    }); 
} 

Esempio di utilizzo:

print(loadImports("<div import='myfragment.txt'></div>")) 
+0

io non sono sicuro di capire che cosa si vuole fare, cioè, quale parte si fa vuoi sostituire con un 'Future '? Il contenuto del file che hai letto all'interno della chiamata a 'replaceAllMapped'? – Tonio

+0

Non esiste una versione integrata di tale funzione, è necessario scriverne una che si aspetti che la funzione di callback sia asincrona, come Tonio di seguito. – lrn

risposta

2

Prova questo:

Future<String> replaceAllMappedAsync(String string, Pattern exp, Future<String> replace(Match match)) async { 
    StringBuffer replaced = new StringBuffer(); 
    int currentIndex = 0; 
    for(Match match in exp.allMatches(string)) { 
    String prefix = match.input.substring(currentIndex, match.start); 
    currentIndex = match.end; 
    replaced 
     ..write(prefix) 
     ..write(await replace(match)); 
    } 
    replaced.write(string.substring(currentIndex)); 
    return replaced.toString(); 
} 

Per usare il tuo esempio di cui sopra:

Future<String> loadImports(String content) async { 
    RegExp exp = new RegExp("import=[\"\']([^\"\']*)[\"\']>\\s*<\/"); 

    return replaceAllMappedAsync(content, exp, (match) async { 
     String filePath = match.group(1); 

     File file = new File(filePath); 
     String fileContent = await file.readAsString(); 
     return ">$fileContent</"; 
    }); 
} 

E usato in questo modo:

loadImports("<div import='myfragment.txt'></div>").then(print); 

o, se utilizzato in un async funzione:

print(await loadImports("<div import='myfragment.txt'></div>")); 
+1

Si consiglia di utilizzare un 'StringBuffer' per raccogliere le parti anziché utilizzare la concatenazione ripetuta con il tempo di esecuzione potenzialmente quadratico. In alternativa, raccogli le parti in una lista e usa "List.join" alla fine. – lrn

+0

Vero ... ha modificato la risposta per utilizzare 'StringBuffer' invece della concatenazione/interpolazione delle stringhe. – Tonio

+1

C'è un piccolo errore di battitura nella tua soluzione. Non dovrebbe esserci un punto e virgola dopo ..write (prefisso). Grazie per una soluzione di lavoro. La transizione dal vero sviluppo multithread al ciclo degli eventi è sorprendentemente difficile. – Zig158

Problemi correlati