await引入dart中的程序有什么后果?
What the consequence does await introduce the program in dart?
为什么下面的代码有效?我认为应该有编译时错误。我认为正文 return 中的 return
是 int
(值 1
)。如果不是,它一定是 returning 一个 Future
,它也不符合 return 类型。 await
发生了什么事?
void longRun() async {
return await Future.delayed(
Duration(seconds: 3),
()=>1,
);
}
如果我将 await
部分分配给一个变量,如下所示,编译器开始报错,这很明显也很容易理解。但是为什么上面的代码没有报错?
void longRun() async {
var foo = await Future.delayed(
Duration(seconds: 3),
()=>1,
);
return foo;
}
继续研究我发现了更令人困惑的事情:以下所有版本都有效。它们看起来完全相同,连线。
版本 1:
void longRun() async {
return await Future.delayed(Duration(seconds:2), ()=>1);
}
版本 2:
Future<void> longRun() async {
return await Future.delayed(Duration(seconds:2), ()=>1);
}
版本 3:
Future<int> longRun() async {
return await Future.delayed(Duration(seconds:2), ()=>1);
}
版本 4:
Future longRun() async {
return await Future.delayed(Duration(seconds:2), ()=>1);
}
版本 5:
Future longRun() async {
await Future.delayed(Duration(seconds:2), ()=>1);
}
版本 6:
void longRun() async {
await Future.delayed(Duration(seconds:2), ()=>1);
}
这主要是关于 =>
的行为,而不是关于 await
的行为。通常 () => 1
可以被认为是 () { return 1; }
的 shorthand,但这实际上过于简单化了。
=>
被允许用于 void
函数以方便人们可以这样写:
bool functionWithSideEffect() {
print('Some side effect');
return true;
}
void foo() => functionWithSideEffect();
int _someValue = 0;
set someValue(int value) => _someValue = value;
即使这些不合法:
var foo() {
// error: A value of type 'bool' can't be returned from the function 'foo'
// because it has a return type of 'void'.
return functionWithSideEffect();
}
set someValue(int value) {
// error: A value of type 'int' can't be returned from the function
// 'someValue' because it has a return type of 'void'.
return _someValue = value;
}
你的困惑的症结在于 () => 1
可能是 int Function()
或 void Function()
,并且类型推断会根据不同的约束选择不同的东西。
当你这样做时:
void longRun() async {
return await Future.delayed(
Duration(seconds: 3),
()=>1,
);
}
然后类型推断从外向内工作,通过不受约束的 returned 表达式传播 longRun
的 void
return 类型。 Future.delayed
调用被推断为 Future<void>.delayed
,() => 1
回调被推断为 void Function()
。 (可以说 void
async
函数 returning Future<void>
可以被视为错误。)
相比之下,当您这样做时:
void longRun() async {
var foo = await Future.delayed(
Duration(seconds: 3),
()=>1,
);
return foo;
}
现在类型推断在 other 方向(由内而外)运行:foo
没有显式类型,因此它不约束右侧.因此 () => 1
被假定为 int Function()
,这导致 Future.delayed
被推断为 Future<int>.delayed
并且 foo
被推断为 int
.由于 foo
是一个 int
,因此尝试从声明为 return void
的函数 return 它是错误的。
version2:
Future<void> longRun() async {
return await Future.delayed(Duration(seconds:2), ()=>1);
}
您已将 longRun
的 return 类型从 void
更改为 Future<void>
。 。与版本 1 的唯一区别是调用者现在可以在 longRun
完成时等待(触发回调)。 () => 1
仍被推断为 void Function()
。
version3:
Future<int> longRun() async {
return await Future.delayed(Duration(seconds:2), ()=>1);
}
除 longRun
returns Future<int>
而不是 Future<void>
外,与版本 2 相同。现在 () => 1
被推断为 int Function()
.
version4:
Future longRun() async {
return await Future.delayed(Duration(seconds:2), ()=>1);
}
longRun
的 return 类型现在是 Future
,这意味着 Future<dynamic>
。 () => 1
被推断为 dynamic Function()
。
version5:
Future longRun() async {
await Future.delayed(Duration(seconds:2), ()=>1);
}
除了没有明确的 return
声明外,与版本 4 相同。现在 Future.delayed
表达式不再受限于 longRun
的 return 类型,推理将由内而外; () => 1
假定为 int Function()
。
version6:
void longRun() async {
await Future.delayed(Duration(seconds:2), ()=>1);
}
除了 longRun
returns void
并且是一个即发即弃函数外,与版本 5 相同。 longRun
完成后无法通知来电者。
(注意上面我写的() => 1
被推断为int Function()
或void Function()
,实际上应该是FutureOr<int> Function()
或FutureOr<void> Function()
, 但这不是重要的部分。)
编辑:
预先解决一些潜在的后续问题:
为什么是:
void longRun() async {
int f() {
return 1;
}
return await Future<void>.delayed(
Duration(seconds: 3),
f,
);
}
好的,但是:
void longRun() async {
return await Future<void>.delayed(
Duration(seconds: 3),
// info: Don't assign to void.
() {
return 1;
},
);
}
生成分析投诉?这两个版本都是合法的,因为当 U
是 T
的子类型时,用 Future<U>
替换 Future<T>
是合法的。当T
是void
时,U
可以是任何东西;该值可以忽略不计。 (在 Dart 中,部分由于历史原因,当它并不总是具有 void
类型时,void
实际上意味着该值不能使用,而不是没有值。void x = 42;
是合法,但试图读取 x
的值将是一个错误。这就是为什么“不要分配给 void”分析投诉未归类为错误的原因。)
在使用匿名函数的第二个版本中,return
语句的更严格的局部性允许分析器执行更广泛的检查。
为什么下面的代码有效?我认为应该有编译时错误。我认为正文 return 中的 return
是 int
(值 1
)。如果不是,它一定是 returning 一个 Future
,它也不符合 return 类型。 await
发生了什么事?
void longRun() async {
return await Future.delayed(
Duration(seconds: 3),
()=>1,
);
}
如果我将 await
部分分配给一个变量,如下所示,编译器开始报错,这很明显也很容易理解。但是为什么上面的代码没有报错?
void longRun() async {
var foo = await Future.delayed(
Duration(seconds: 3),
()=>1,
);
return foo;
}
继续研究我发现了更令人困惑的事情:以下所有版本都有效。它们看起来完全相同,连线。
版本 1:
void longRun() async {
return await Future.delayed(Duration(seconds:2), ()=>1);
}
版本 2:
Future<void> longRun() async {
return await Future.delayed(Duration(seconds:2), ()=>1);
}
版本 3:
Future<int> longRun() async {
return await Future.delayed(Duration(seconds:2), ()=>1);
}
版本 4:
Future longRun() async {
return await Future.delayed(Duration(seconds:2), ()=>1);
}
版本 5:
Future longRun() async {
await Future.delayed(Duration(seconds:2), ()=>1);
}
版本 6:
void longRun() async {
await Future.delayed(Duration(seconds:2), ()=>1);
}
这主要是关于 =>
的行为,而不是关于 await
的行为。通常 () => 1
可以被认为是 () { return 1; }
的 shorthand,但这实际上过于简单化了。
=>
被允许用于 void
函数以方便人们可以这样写:
bool functionWithSideEffect() {
print('Some side effect');
return true;
}
void foo() => functionWithSideEffect();
int _someValue = 0;
set someValue(int value) => _someValue = value;
即使这些不合法:
var foo() {
// error: A value of type 'bool' can't be returned from the function 'foo'
// because it has a return type of 'void'.
return functionWithSideEffect();
}
set someValue(int value) {
// error: A value of type 'int' can't be returned from the function
// 'someValue' because it has a return type of 'void'.
return _someValue = value;
}
你的困惑的症结在于 () => 1
可能是 int Function()
或 void Function()
,并且类型推断会根据不同的约束选择不同的东西。
当你这样做时:
void longRun() async { return await Future.delayed( Duration(seconds: 3), ()=>1, ); }
然后类型推断从外向内工作,通过不受约束的 returned 表达式传播 longRun
的 void
return 类型。 Future.delayed
调用被推断为 Future<void>.delayed
,() => 1
回调被推断为 void Function()
。 (可以说 void
async
函数 returning Future<void>
可以被视为错误。)
相比之下,当您这样做时:
void longRun() async { var foo = await Future.delayed( Duration(seconds: 3), ()=>1, ); return foo; }
现在类型推断在 other 方向(由内而外)运行:foo
没有显式类型,因此它不约束右侧.因此 () => 1
被假定为 int Function()
,这导致 Future.delayed
被推断为 Future<int>.delayed
并且 foo
被推断为 int
.由于 foo
是一个 int
,因此尝试从声明为 return void
的函数 return 它是错误的。
version2:
Future<void> longRun() async { return await Future.delayed(Duration(seconds:2), ()=>1); }
您已将 longRun
的 return 类型从 void
更改为 Future<void>
。 longRun
完成时等待(触发回调)。 () => 1
仍被推断为 void Function()
。
version3:
Future<int> longRun() async { return await Future.delayed(Duration(seconds:2), ()=>1); }
除 longRun
returns Future<int>
而不是 Future<void>
外,与版本 2 相同。现在 () => 1
被推断为 int Function()
.
version4:
Future longRun() async { return await Future.delayed(Duration(seconds:2), ()=>1); }
longRun
的 return 类型现在是 Future
,这意味着 Future<dynamic>
。 () => 1
被推断为 dynamic Function()
。
version5:
Future longRun() async { await Future.delayed(Duration(seconds:2), ()=>1); }
除了没有明确的 return
声明外,与版本 4 相同。现在 Future.delayed
表达式不再受限于 longRun
的 return 类型,推理将由内而外; () => 1
假定为 int Function()
。
version6:
void longRun() async { await Future.delayed(Duration(seconds:2), ()=>1); }
除了 longRun
returns void
并且是一个即发即弃函数外,与版本 5 相同。 longRun
完成后无法通知来电者。
(注意上面我写的() => 1
被推断为int Function()
或void Function()
,实际上应该是FutureOr<int> Function()
或FutureOr<void> Function()
, 但这不是重要的部分。)
编辑:
预先解决一些潜在的后续问题:
为什么是:
void longRun() async {
int f() {
return 1;
}
return await Future<void>.delayed(
Duration(seconds: 3),
f,
);
}
好的,但是:
void longRun() async {
return await Future<void>.delayed(
Duration(seconds: 3),
// info: Don't assign to void.
() {
return 1;
},
);
}
生成分析投诉?这两个版本都是合法的,因为当 U
是 T
的子类型时,用 Future<U>
替换 Future<T>
是合法的。当T
是void
时,U
可以是任何东西;该值可以忽略不计。 (在 Dart 中,部分由于历史原因,当它并不总是具有 void
类型时,void
实际上意味着该值不能使用,而不是没有值。void x = 42;
是合法,但试图读取 x
的值将是一个错误。这就是为什么“不要分配给 void”分析投诉未归类为错误的原因。)
在使用匿名函数的第二个版本中,return
语句的更严格的局部性允许分析器执行更广泛的检查。