Dart彙總請點擊這裏
問題
假設調用了REST服務,當該服務返回數據時,Future將完成,顯示也會隨之更新。這種情況可能類似於以下情況:
main() async {
List data = await getData();
updateDisplay(data);
}
Future<List> getData() async {
// make the REST call
Response restResponse = await HttpRequest.get(.....);
// massage the data
List data = restResponse.response.map((Map record) {
// transform/check raw records
// return good data
});
return data;
}
void updateDisplay(List data) {
// update the display
}
如果該REST調用花費很長時間,如果您的用戶變得不耐煩並且導航離開了首先需要數據的視圖怎麼辦?
解決方案
很多人都知道,無法取消Dart中的Future,但是可以取消Stream的訂閱。因此,處理這種情況的一種方法是重寫getData()以返回Stream。
幸運的是,可以輕鬆地從調用方將Future轉換爲Stream:
void main() {
// keep a reference to your stream subscription
StreamSubscription<List> dataSub;
// convert the Future returned by getData() into a Stream
dataSub = getData().asStream().listen((List data) {
updateDisplay(data);
});
// user navigated away!
dataSub.cancel();
}
使用Future的asStream()方法,基本上可以將Future當作一個Stream來listen。這樣,如果發現不再需要尚未到達的數據,則可以保存您的訂閱並使用它取消回調。所有這些都無需修改getData()功能。
真正發生了什麼
實際上不可能阻止Future的完成。
所能做的就是在特定情況下(例如,響應在返回之前變得無關緊要)停止執行回調。
在代碼示例中,dataSub.cancel()在Future完成之前調用即可實現此目的。
使用此方法的更實際的應用場景:
// keep a reference to your stream subscription
StreamSubscription<List> dataSub;
void onGetDataClicked() {
// make sure any still-pending prior request never gets processed
dataSub?.cancel();
// convert the Future returned by getData() into a Stream
dataSub = getData().asStream().listen((List data) {
updateDisplay(data);
});
}
通過此流程,可以確保只有最新的數據請求最終顯示。