future.then 块在返回类型整数的函数内跳过导致返回 null
Posted
技术标签:
【中文标题】future.then 块在返回类型整数的函数内跳过导致返回 null【英文标题】:future.then block skipped inside function of return type integer causes to return null 【发布时间】:2020-04-02 19:31:21 【问题描述】:我偶然发现了一个奇怪的问题。
以下函数获取 Firestore 文档并将其返回,以便其他函数可以访问它的数据
Future getCountRequests() async
try
return await _countReference.document('Requests').get();
catch(e)
print(e.toString());
这就是使用它的数据的函数。
int _countRequest()
int toReturn;
CounterService().getCountRequests().then(
(doc)
//print('Item in question: $doc, information from document $doc.data');
//this line prints correctly Instance of DocumentReference and "amount" : 6
toReturn = doc.data['amount'];
);
return toReturn;
当我运行代码时,我在屏幕上收到一条错误消息,指出我正在使用的 AnimatedList
从 _countRequest()
函数接收到 null。
在这一行打断有助于我理解这个块被完全跳过
CounterService().getCountRequests().then( ...
但是,当我在这一行上打断时,它表明块内的代码有效,并且确实通过getCountRequests()
函数接收到该文档。
toReturn = doc.data['amount'];
我的问题是,是什么导致 .then
块被跳过导致函数返回 null?
【问题讨论】:
您应该在要获取的未来函数之前添加await
。
请参阅这些指南 [1] 以了解“等待”的一些示例。 [1]dart.dev/codelabs/…
是的,我访问了这些页面。根据我从其他几篇文章的理解,“then”函数应该可以从异步函数中获取值并使其在同步函数中可用。这就是我在这里尝试的,所以这让我想知道我做错了什么。
then()
方法在您从_countRequest
方法返回后被调用,这就是您得到null
的原因,因为toReturn
没有设置为它的任何值声明
感谢您的回复,我明天会尝试您的解决方案,如果它有效,请告诉您。
【参考方案1】:
你试图做的事情行不通。
您正在尝试从同步函数返回异步计算的结果。没有办法让它发挥作用。 异步计算总是稍后完成,同步函数总是返回now,所以现在不能返回计算结果。
then
调用是使操作异步的原因。它将回调传递给未来,但唯一可以保证当回调被调用时,它肯定是不是立即的。 then
调用立即返回,返回一个将在回调被调用时完成的未来,并且您的代码返回toReturn
的当前值,它仍然是null
。
【讨论】:
【参考方案2】:最后,我发现用FutureBuilder
异步执行此操作根本行不通,或者以我目前的技能组合,我只是不知道如何使它工作。所以我决定转换为StreamBuilder
,它使用从以下函数获得的Stream<QuerySnapshot>
。
Stream<QuerySnapshot> findAllRequests()
try
return accountRequestCollection.snapshots();
catch(e)
print(e.toString());
return null;
并像这样将AnimatedList
构建到StreamBuilder
中。
class Request extends StatefulWidget
@override
_RequestState createState() => _RequestState();
class _RequestState extends State<Request>
final AdministrationService _administrationService = AdministrationService();
final GlobalKey<AnimatedListState> _globalKey = GlobalKey();
@override
Widget build(BuildContext context)
return Scaffold(
appBar: AppBar(
title: Text('Account Requests'),
),
body: StreamBuilder(
stream: _administrationService.findAllRequests(),
builder: (BuildContext context, AsyncSnapshot<QuerySnapshot> snapshot)
switch (snapshot.connectionState)
case ConnectionState.waiting: return new Loading();
default: if (snapshot.hasError)
return new Text('Error: $snapshot.hasError');
else
return AnimatedList(
key: _globalKey,
initialItemCount: snapshot.data.documents.length,
itemBuilder: (BuildContext context, int index, Animation animation)
return _buildItem(snapshot.data.documents[index].data['email'], animation);
);
)
);
Widget _buildItem(String item, Animation animation)
return SizeTransition(
sizeFactor: animation,
child: Card(
child: ListTile(
title: Text(
item,
style: TextStyle(
fontSize: 20.0,
)
),
),
),
);
它会进入这个页面。 Emulator Screenshot。 我希望这个解决方案可以帮助其他有类似问题的人,但考虑到这只是一个概念验证产品,我不确定这在 Firestore 读/写方面会付出多大的代价。
【讨论】:
以上是关于future.then 块在返回类型整数的函数内跳过导致返回 null的主要内容,如果未能解决你的问题,请参考以下文章
FlutterFuture 异步编程 ( 简介 | then 方法 | 异常捕获 | asyncawait 关键字 | whenComplete 方法 | timeout 方法 )