String.replaceAllMapped with asynchronous result

I am working on a project that requires templates. The main template has an import attribute that indicates the data source. Then the data is read and pasted into the string using String.replaceAllMapped. The following code works fine with the api file since it has a readAsStringSync method for reading the file synchronously. Now I want to read any arbitrary stream that returns the future.

How to make async / wait work in this scenario? I also looked for an asynchronous compatible replacement for replaceAllMapped, but I did not find a solution that does not require multiple passes with a regex.

Here is a very simplified example of my code:

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</"; }); } 

Usage example:

 print(loadImports("<div import='myfragment.txt'></div>")) 
+5
source share
1 answer

Try the following:

 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(); } 

To use your example above:

 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</"; }); } 

And used like this:

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

or, if used in async function:

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

Source: https://habr.com/ru/post/1238559/


All Articles