UI动画与异步请求结合的最佳实践?

时间:2019-12-08 16:24:52

标签: javascript user-interface animation

我正在构建一个老虎机游戏,一开始很容易实现UI动画,但是当我不得不从后端服务中获取结果时,我发现很难将它与异步请求结合起来。

想象我有一个老虎机模块,我可以这样使用:

import SlotMachine from './slot-machine';
const sm = new SlotMachine();
document.querySelector('#button').addEventListener('click', () => {
  // keep running for 5 seconds and display result as [1, 2, 3]
  sm.animateTo({
    duration: 5000,
    result: [1, 2, 3]
  });
});

到目前为止还不错,但是当我想从后端服务中获取结果时,将是这样的:

import SlotMachine from './slot-machine';
const sm = new SlotMachine();
document.querySelector('#button').addEventListener('click', () => {
  fetch('/api/getResult').then((result) => {
    sm.animateTo({
      duration: 5000,
      result: result
    });
  });
});

但是此实现中的用户体验不是很好,在用户单击按钮后,动画直到fetch请求完成后才开始播放,在网络连接缓慢的情况下更是如此。

所以我必须像这样更改我的slot-machine api:

import SlotMachine from './slot-machine';
const sm = new SlotMachine();
document.querySelector('#button').addEventListener('click', () => {
  const fakeStartTime = Date.now();
  sm.startFakeAnimation();
  fetch('/api/getResult').then((result) => {
    sm.stopFakeAnimation();
    const fakeEndTime = Date.now();
    sm.animateTo({
      duration: 5000 - (fakeEndTime - fakeStartTime),
      result: result
    });
  });
});

这样,用户操作将立即获得响应,但是,我认为实施startFakeAnimationstopFakeAniamtion并不容易,以使其与“真实”动画无缝融合

有没有更好的解决此类问题的方法?

1 个答案:

答案 0 :(得分:0)

拥有一组动画处理程序恕我直言会更有意义:

  1. startAnimation
  2. endAnimationWithResult

必须设置固定时间的动画(在上面的示例中为5秒)的问题是,您永远不知道提取调用将花费多长时间。假设我们已将“ animateTo”调用分为两个调用(“ start”和“ endWithResult”),其余实现将非常简单:

...
const startTime = Date.now()
sm.startAnimation()

const result = await fetch('/api/getResult')
const endTime = Date.now()
const delayTime = Math.max(5000 - (endTime - startTime), 0)  // Making sure we always spin for at least 5 sec
await new Promise(resolve => setTimeout(resolve, delayTime)) // Add delay to make sure we sping for at least 5 sec

sm.endAnimationWithResult(result)  // Stop spinning wheels and display the numbers
...

这样,您将不必处理两个动画序列的同步,而且代码对单元测试更友好。由于SlotMachine类已经实现了固定长度的动画,因此将其分为两种方法在IMO中并不难。

希望有帮助!