如何对从包含异步的函数返回的值使用 List.sort?

Posted

技术标签:

【中文标题】如何对从包含异步的函数返回的值使用 List.sort?【英文标题】:How to use List.sort on values returned from a function that contains an async? 【发布时间】:2020-01-29 06:38:28 【问题描述】:

我有这个代码:

 widget.items.sort((a, b) 

           await getItemDistance(a, true);
          await getItemDistance(b, false);

          return (itemADistance)
              .compareTo(itemBDistance);
        );

我正在尝试根据从 getItemDistance 返回的值对 widget.items 列表进行排序。但是,我收到一条红色波浪线错误,上面写着:

await 表达式只能在异步函数中使用

当我尝试将异步添加到排序方法时,我得到另一条红色波浪线:

无法分配参数类型“Future Function(Item, Item)” 到参数类型'int Function(Item, Item)'

我该如何解决这个难题? :) 谢谢

【问题讨论】:

【参考方案1】:

每当您运行异步代码时,您都应该添加如下所示的 async 关键字。这告诉 dart 你打算运行异步代码。

异步函数返回一个 Future,它告诉 dart 在未来的某个时间点你期待 itemADistance 或一个错误。

您将希望返回 int 类型的 Future,因为您希望收到 int itemADistance 或错误。

   Future<int> widget.items.sort((a, b) async 

                   await getItemDistance(a, true);
                  await getItemDistance(b, false);

                  return (itemADistance)
                      .compareTo(itemBDistance);
                );

【讨论】:

您好帕特里克,感谢您的及时答复。但是,当我尝试此代码时,出现此错误:无法将参数类型“Future Function(Item, Item)”分配给参数类型“int Function(Item, Item)” 如果您以后使用 return 关键字,您应该告诉 dart 您希望将来收到什么类型。如果您没有返回任何内容,请告诉它 Future 还是不行。它显示一个错误:期待;。 List.sort 是同步的,并且需要一个同步回调(即,一个返回 int,而不是 Future&lt;int&gt; 的函数)。它不能与异步回调一起使用。【参考方案2】:

List.sort 是一个同步函数,需要一个同步回调;无法将它与异步回调一起使用。我建议您转换您的 List 并执行任何必要的异步工作firstthen 同步排序结果。这样做还应该避免在同一个项目上多次调用getItemDistance(由于是异步的,这可能很昂贵)。例如,类似:

final computedDistances = <Item, double>;
for (final item in widget.items) 
  final distance = await getItemDistance(item, ...);
  computedDistances[item] = distance;


widget.items.sort((a, b) => 
  computedDistances[a].compareTo(computedDistances[b])
);

(我不知道getItemDistance 的第二个参数代表什么;如果您无法解决这个问题,则需要构建一个带有getItemDistance(..., true) 结果的Map 和一个带有getItemDistance(..., false) 结果的Map。 )

作为最后的手段,您可以编写自己的异步排序函数。


编辑

这应该是一个更高效的版本,因为它不会一个接一个地等待每个异步操作:

final computedDistances = await Future.wait<double>([
  for (final item in widget.items) getItemDistance(item, ...),
]);

final computedDistancesMap = <Item, double>
  for (var i = 0; i < widget.items.length; i += 1)
    widget.items[i]: computedDistances[i],
;

widget.items.sort((a, b) => 
  computedDistancesMap[a].compareTo(computedDistancesMap[b])
);

【讨论】:

以上是关于如何对从包含异步的函数返回的值使用 List.sort?的主要内容,如果未能解决你的问题,请参考以下文章

当for内部有查询时如何返回异步函数的值

如何在颤动中返回异步函数的值?

如何使用 Select2.js 对从 Ajax 调用返回的数据进行多选结果?

nodejs如何从异步回调函数返回想要的值

如何将包装在 Promise 中的值传递给非异步函数? [复制]

如何将Ext.Ajax.request请求 返回的值赋值给全局变量