2015-12-17 17 views
5

Tôi đang làm việc trên một dự án yêu cầu mẫu. Mẫu chính có thuộc tính import xác định nguồn dữ liệu. Dữ liệu sau đó được đọc và chèn vào chuỗi bằng String.replaceAllMapped. Đoạn mã sau hoạt động tốt với File api vì nó có phương thức readAsStringSync để đọc tệp một cách đồng bộ. Bây giờ tôi muốn đọc từ bất kỳ luồng tùy ý nào trả về một Tương lai.String.replaceAllMapped với kết quả không đồng bộ

Làm cách nào để tôi thực hiện công việc không đồng bộ/đang chờ xử lý trong trường hợp này? Tôi cũng đã tìm kiếm một thay thế tương thích async cho replaceAllMapped nhưng tôi đã không tìm thấy một giải pháp mà không yêu cầu nhiều pass với regex.

Dưới đây là một ví dụ rất đơn giản của mã của tôi:

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

Ví dụ sử dụng:

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

Tôi không chắc tôi hiểu những gì bạn muốn làm, đó là, phần nào làm bạn muốn thay thế bằng 'Tương lai '? Nội dung tệp bạn đã đọc bên trong cuộc gọi đến 'replaceAllMapped'? – Tonio

+0

Không có phiên bản tích hợp của chức năng như vậy, bạn phải viết một phiên bản mà chức năng gọi lại là không đồng bộ, giống như Tonio bên dưới. – lrn

Trả lời

2

Hãy thử điều này:

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

Để sử dụng ví dụ của bạn ở trên:

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

Và sử dụng như thế này:

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

hoặc, nếu sử dụng trong một async chức năng:

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

Tôi khuyên bạn nên sử dụng một 'StringBuffer' để thu thập các phần thay vì sử dụng nối lại lặp lại với thời gian thực hiện có khả năng bậc hai. Ngoài ra, chỉ cần thu thập các phần trong danh sách và sử dụng 'List.join' ở cuối. – lrn

+0

True ... đã chỉnh sửa câu trả lời để sử dụng 'StringBuffer' thay vì chuỗi nối/nội suy. – Tonio

+1

Có một lỗi đánh máy nhỏ trong giải pháp của bạn. Không nên có dấu chấm phẩy sau ..write (tiền tố). Cảm ơn bạn vì một giải pháp làm việc. Quá trình chuyển đổi từ phát triển đa luồng thực sự sang vòng lặp sự kiện gây khó khăn đáng ngạc nhiên. – Zig158

Các vấn đề liên quan