显示 angulardart 进展的最佳做法是什么?

What is the best practice to show a progress in angulardart?

我试图展示 angulardart 的进步,并认为 Future 对此有好处。但后来我意识到 Future 必须递归才能显示进度,因为 Future returns 立即执行,然后执行冗长的操作。

如果我创建一个在满足结束条件之前调用自身的 Future,它将与进度条一起工作。但我认为这不是一个很好的做法,因为每次递归时这些调用都会增加堆栈上的内存。只需考虑一个遍历 10 亿个数据集的循环,该循环可能 运行 几个小时,并且每个循环都在当前 Future 中调用一个新的 Future。

是否有更好的方法来创建一个循环,该循环需要一定的时间来处理每个元素(包括调用必须异步完成的网站并评估 return 值)?在循环期间,用户应该看到显示他 "x/1000000 done".

的进度

我认为必须用 Future 来完成,因为 UI 需要在启动循环后重新加载,但递归 Future 对我来说似乎不是个好主意。

您需要未来立即在网络上 return 返回给您,因为它是一个单线程平台。如果异步操作 return 直到它完成,那么你就会挂起浏览器,这对用户来说不会是一个很好的体验。

相反,您有几个选择:

Dart 有能力让 future 看起来像是与 await 关键字同步。所以你可以这样做:

void performAction() async {
  showProgress = true;
  await expensiveRpc();
  showProgress = false;
}

这需要中间的进度,因为您实际上并没有在进度条进行时更新进度条。也就是说,如果您没有真正从 RPC 获取进度事件,这可能是更好的解决方案。

现在,如果您的 RPC 或操作在进行过程中给您某种反馈,您可以使用流做一些更好的事情。

void performAction() {
  showProgress = true;
  expensiveRpc().listen((progress) {
    if (progress.done) {
      showProgress = false;
    } else {
      percentComplete = progress.value;
    });
}

实际上,与进度本身相比,它更多地取决于与您交互的 RPC 或服务如何更好地更新进度。

与此同时,我立即认识到一个 Future 方法 returns 而无需在方法体中执行任何操作。所以解决方案很简单:

只要用一个Future声明rpc,在方法中做任何你需要做的,在调用它的时候,使用then(...)做你需要在收集数据后做的事情。

int progress = 0;
int progressMax = 100;
bool progressCanceled = false;

Future rpc(var data)
async{
  for(progress=0; progress<progressMax, progress++)
  {
    // do whatever you need to do with data
    if(progressCanceled)
      return;
  }
}

rpc(data).then(
{
  if(progressCanceled)
    return;
  // do whatever is needed after having received that data
});

rpc 已执行,调用进程可以继续,同时 rpc 执行 rpc 必须执行的操作。主程序可以处理按钮点击以将 progressCanceled 设置为 true,rpc 方法将询问状态并在设置时停止处理。