Dart彙總請點擊這裏
Future
Future模型是將異步請求和代理模式結合的產物。
Future類是對未來結果的一個代理,它返回的並不是被調用的任務的返回值。
//我的任務
void myTask(){
print("this is my task");
}
void main() {
Future fut = new Future(myTask);//根據我的任務創建Future對象
}
如上代碼,Future類實例fut並不是函數myTask的返回值,它只是代理了myTask函數,封裝了該任務的執行狀態。換種理解方式就是,Future就是一個受你委託的委託人,你將未來要執行的任務交給他,你告知他任務類型是耗時任務,還是非耗時任務,然後分類放到事件循環中去,當任務完成後,它會第一時間執行回調方法告知你任務完成,或者會等到你委託給他的所有任務都完成了立馬告知你。
創建Future
Future的幾種創建方法
Future()
Future.microtask()
Future.sync()
Future.value()
Future.delayed()
Future.error()
其中sync是同步方法,任務會被立即執行
import 'dart:async';
void main() {
print("main start");
new Future.sync((){
print("sync task");
});
new Future((){
print("async task");
});
print("main stop");
}
運行結果:
main start
sync task
main stop
async task
註冊回調
使用then註冊回調
當Future中的任務完成後,我們往往需要一個回調,這個回調立即執行,不會被添加到事件隊列。
import 'dart:async';
void main() {
print("main start");
Future fut =new Future.value(18);
// 使用then註冊回調
fut.then((res){
print(res);
});
// 鏈式調用,可以跟多個then,註冊多個回調
new Future((){
print("async task");
}).then((res){
print("async task complete");
}).then((res){
print("async task after");
});
print("main stop");
}
運行結果:
main start
main stop
18
async task
async task complete
async task after
除了then方法,還可以使用catchError來處理異常,如下
new Future((){
print("async task");
}).then((res){
print("async task complete");
}).catchError((e){
print(e);
});
還可以使用靜態方法wait 等待多個任務全部完成後回調。
import 'dart:async';
void main() {
print("main start");
Future task1 = new Future((){
print("task 1");
return 1;
});
Future task2 = new Future((){
print("task 2");
return 2;
});
Future task3 = new Future((){
print("task 3");
return 3;
});
Future fut = Future.wait([task1, task2, task3]);
fut.then((responses){
print(responses);
});
print("main stop");
}
運行結果:
main start
main stop
task 1
task 2
task 3
[1, 2, 3]
如上,wait返回一個新的Future,當添加的所有Future完成時,在新的Future註冊的回調將被執行。
Future的特點
-
Future中的then並沒有創建新的Event丟到Event Queue中,而只是一個普通的Function Call,在FutureTask執行完後,立即開始執行
-
Future如果在then()調用之前Future就已經執行完畢了,那麼會有一個任務被加入到microtask隊列中。這個任務執行的就是被傳入then的方法
-
Future只是創建了一個Event,將Event插入到了Event Queue的隊尾
-
Future.value創建Task到microtask Queue中執行then傳入的函數
-
Future.sync執行了它傳入的函數之後,也會立即創建Task丟到microtask Queue中執行
-
Future.wait等待多個任務全部完成後回調。wait返回一個新的Future,當添加的所有Future完成時,在新的Future註冊的回調將被執行。
-
Future.delayed在延時一定時間後向隊列插入一個任務
雖然可以預測任務執行的順序,但是我們無法預測事件循環什麼時候會從隊列中提取任務。Dart事件處理系統基於單線程循環,而不是基於時基(tick,系統的相對時間單位)或者其他的時間度量。例如,當你創建一個延時1s的任務,1s後向事件隊列添加一個任務,但在該任務之前的任務結束前,事件循環是不會處理這個任務的,也就是說該任務執行可能是大於1s的。
async 和 await
在Dart1.9中加入了async和await關鍵字,有了這兩個關鍵字,我們可以更簡潔的編寫異步代碼,而不需要調用Future相關的API。他們允許你像寫同步代碼一樣寫異步代碼和不需要使用Future接口。
將 async 關鍵字作爲方法聲明的後綴時,具有如下意義
被修飾的方法會將一個 Future 對象作爲返回值
該方法會同步執行其中的方法的代碼直到第一個 await 關鍵字,然後它暫停該方法其他部分的執行;
一旦由 await 關鍵字引用的 Future 任務執行完成,await的下一行代碼將立即執行。
// 導入io庫,調用sleep函數
import 'dart:io';
// 模擬耗時操作,調用sleep函數睡眠2秒
doTask() async{
await sleep(const Duration(seconds:2));
return "Ok";
}
// 定義一個函數用於包裝
test() async {
var r = await doTask();
print(r);
}
void main(){
print("main start");
test();
print("main end");
}
運行結果:
main start
main end
Ok
注意:需要注意,async 不是並行執行,它是遵循Dart 事件循環規則來執行的,它僅僅是一個語法糖,簡化Future API的使用。
Future 原理
Dart 是事件驅動的體系結構,該結構基於具有單個事件循環和兩個隊列的單線程執行模型。 Dart雖然提供調用堆棧。 但是它使用事件在生產者和消費者之間傳輸上下文。 事件循環由單個線程支持,因此根本不需要同步和鎖定。
詳細請參閱我的另一篇文章: Dart 事件循環
使用 Future 控制任務調度
將任務添加到MicroTask隊列立即執行或將任務添加到Event隊列空閒執行
詳細請參閱我的另一篇文章:Dart 任務調度