前端的同學對Promise
肯定都很熟悉,而Future
便是dart
中Promise
,但方法名稱和使用方式還是有些許的差異的。
下面我們嘗試塞栅,利用Future
封裝出js中我們熟悉的Promise
。
Javascript Promise 參考
https://es6.ruanyifeng.com/#docs/promise
實現(xiàn)Promise的基本用法
import 'dart:async';
class Promise {
Future future;
Promise(dynamic excutor(dynamic resolve(val), dynamic reject(val))) {
if (!(excutor is Function)) {
throw new AssertionError('Promise resolver $excutor is not a function');
}
final completer = Completer();
try {
excutor(completer.complete, completer.completeError);
} catch (e) {
completer.completeError(e);
}
this.future = completer.future;
}
/// Promise鏈式回調(diào)腔丧,對應Dart [.then]
Future then(Future Function(dynamic) onValue, {Function onError}) {
return this.future?.then(onValue, onError: onError);
}
/// Promise鏈式回調(diào)放椰,對應Dart [.catchError]
Future catch_(Function onError, {bool Function(Object) test}) {
return this.future?.catchError(onError, test: test);
}
/// Promise鏈式回調(diào)作烟,對應Dart [.whenComplete]
Future finally_(Future<dynamic> Function() action) {
return this.future?.whenComplete(action);
}
}
使用示例
Promise promise = Promise((resolve,reject){
// ... some code
if (/* 異步操作成功 */){
resolve(value);
} else {
reject(error);
}
})
// 鏈式回調(diào)
promise
.then((value) => null)
.catch_((error) => null)
.finally_((action) => null);
// 如果要使用dart的 async/await 需要先獲取到 Promise 實例內(nèi)的 Future
dynamic result = await promise.future;
Futrue中有對應實現(xiàn)的方法
Promise.all
, Promise.race
, Promise.resolve
, Promise.reject
class Promise{
/// 用于將多個 Future 實例,包裝成一個新的 Future 實例砾医。
/// 等待[futures]完成并收集其結(jié)果拿撩。
static Future all(Iterable<Future> futures) => Future.wait(futures);
/// 對應Dart [Future.any]
/// 返回[futures]中成功完成的第一個future的結(jié)果。
/// 任意失敗都會導致拋出異常
static Future race(Iterable<Future> futures) => Future.any(futures);
/// 對應Dart [Future.value]
static Future resolve(dynamic value) => Future.value(value);
/// 對應Dart [Future.error]
static Future reject(dynamic value) => Future.error(value);
}
Futrue中有無對應實現(xiàn)的方法
Promise.allSettled
方法接受一組 Promise 實例作為參數(shù)藻烤,包裝成一個新的 Promise 實例绷雏。只有等到所有這些參數(shù)實例都返回結(jié)果,不管是fulfilled
還是rejected
怖亭,包裝實例才會結(jié)束。該方法由 ES2020 引入
class Promise{
static final String FULFILLED = 'fulfilled';
static final String REJECTED = 'rejected';
/// 用于將多個 Future 實例坤检,包裝成一個新的 Future 實例兴猩。
/// 不論成功失敗,都返回結(jié)果
static Future allSettled(Iterable<Future> futures) {
List<dynamic> result = List.generate(futures.length, (index) => null);
final completer = Completer();
for (int i = 0; i < futures.length; i++) {
futures.elementAt(i).then((value) {
result[i] = {'status': FULFILLED, 'value': value};
}).catchError((error) {
result[i] = {'status': REJECTED, 'reason': error};
}).whenComplete(() {
if (result.every((element) => element != null)) {
return completer.complete(result);
}
});
}
return completer.future;
}
}
Promise.any()
方法接受一組 Promise 實例作為參數(shù)早歇,包裝成一個新的 Promise 實例倾芝。只要參數(shù)實例有一個變成fulfilled
狀態(tài),包裝實例就會變成fulfilled
狀態(tài)箭跳;如果所有參數(shù)實例都變成rejected
狀態(tài)晨另,包裝實例就會變成rejected
狀態(tài)。該方法目前是一個第三階段的提案 谱姓。
Promise.any()
跟Promise.race()
方法很像借尿,只有一點不同,就是不會因為某個 Promise 變成rejected
狀態(tài)而結(jié)束屉来。
class Promise{
/// 返回[futures]中成功完成的第一個future的結(jié)果;
/// 全部失敗才會拋出異常
/// ```
/// @param futures {Iterable<Future>} Future 實例組
/// @param onlyError {bool} 是否只拋出最后一個異常結(jié)果路翻,否則拋出一個異常 List ,默認 false
/// ```
static Future any(Iterable<Future> futures, {bool onlyError = false}) async {
List<dynamic> errors = [];
final completer = Completer();
for (int i = 0; i < futures.length; i++) {
futures.elementAt(i).then((value) {
completer.complete(value);
}).catchError((error) {
errors[i] = error;
if (futures.length == errors.length) {
completer.completeError(onlyError ? error : errors);
}
});
}
return completer.future;
}
}
順便把延遲函數(shù)
也封裝一下茄靠,畢竟毫秒延遲的使用頻率是最高的茂契。
class Promise{
static Future sleep(int ms) => Future.delayed(Duration(milliseconds: ms));
}