Сделать анимацию холста асинхронной - PullRequest
0 голосов
/ 09 июня 2018

Следующий код является частью большого проекта:

<body>
  <canvas id="check" width="35px" height="40px" style="background-color: blue;"></canvas>
</body>
<script>
  const check = document.getElementById('check');
  const checkCtx = check.getContext('2d');
  check.onclick = function() {
    drawCheck(checkCtx, 5, 30);
    setTimeout(function() {
      fadeOut(check);
    }, 1000);
    setTimeout(function() {
      check.style.opacity = "1";
      checkCtx.clearRect(0, 0, check.width, check.height);
    }, 2000);
    check.style.backgroundColor = "blue";
  }

  function drawCheck(ctx, x, y) {
    var x1 = x;
    var y1 = y;
    var x2 = x1;
    var y2 = y1;
    var x3 = x1 + 14;
    var y3 = y1 + 7;
    ctx.beginPath();
    ctx.strokeStyle = "green";
    ctx.lineCap = "round";
    ctx.lineWidth = 5;
    ctx.moveTo(x1, y1);

    function draw() {
      x2++;
      y2 += .5;
      ctx.lineTo(x2, y2);
      ctx.stroke();
      if (x2 < x1 + 14) {
        requestAnimationFrame(draw);
      } else {
        function drawNext() {
          x3 += .5;
          y3 -= 1.5;
          ctx.lineTo(x3, y3);
          ctx.stroke();
          if (x3 < x1 + 24) {
            requestAnimationFrame(drawNext);
          } else {
            return;
          }
        }
        drawNext();
        return;
      }
    }
    draw();
  }

  function fadeOut(obj) {
    var opc = 1;
    var finish = false;
    obj.style.opacity = 1;

    function fade() {
      opc -= 0.125;
      obj.style.opacity = opc + "";
      console.log(opc);
      if (opc > 0) {
        requestAnimationFrame(fade);
      }
    }
    console.log("Wait for it...");
    fade();
    console.log("Finished!");
  }
</script>

Если вы посмотрите на консоль, вы увидите, что функция fadeOut заканчивается до завершения функции fade.Из-за этого мне приходится использовать несколько setTimeout функций.У других моих функций такая же проблема.Я не хочу полагаться на них, так как я могу заставить код ждать, пока вызванная функция не вернется?

1 Ответ

0 голосов
/ 10 июня 2018

обратный вызов (es5), обещания (es6), async / await (es7)

Вы хотите выполнить код асинхронно.Это означает, что необходимо дождаться, пока код детали завершит работу, прежде чем запускать следующий.Javascript по умолчанию делает все как можно скорее, независимо от того, что.

Неправильно:

function run(){ 
  console.log('1: start run')
  setTimeout(()=>{
    console.log('2: timeout')
  },1000)
}

function run2(){
  console.log('3: start run2')
  setTimeout(()=>{
    console.log('4: timeout')
  },1000) // change time here and check order console.log's
}

function run3(){
  console.log('4: start run3')
  setTimeout(()=>{
    console.log('5: timeout')
  },1000)
}
run()
run2()
run3()

3 функции запускаются одновременно, и они дают результаты, не смотря на то, что происходит в других 2 функциях.Попробуйте изменить время ожидания, чтобы изменить порядок в conole.log.Но в реальной жизни вы не можете контролировать выполнение времени, как здесь.

Обратный вызов:

При обратном вызове вы вкладываете одну функцию в другую, передавая ее в качестве параметра.Идея состоит в том, чтобы дождаться выполнения первой функции, прежде чем начнется вторая ... дождаться второй перед третьей ... и т. Д.

function runWithCallback(callback){ // run1
  console.log('1: start runWithCallback()')
  setTimeout(()=>{
    console.log('2: timeout')
    callback(runAfterCallback)
  },1000)
}

function runCallback(callback){ // run2
  console.log("3: start runCallback()")
  setTimeout(()=>{
    console.log('4: timeout')
    callback()
  },1000)
}

function runAfterCallback(){ // run3
  console.log("5: start runAfterCallback()")
  setTimeout(()=>{
    console.log('6: timeout')
    // next call back here if needed
  },1000)
}

runWithCallback(runCallback)

Теперь не имеет значения, сколько будет длиться время выполнения каждой функции, следующая будет запускаться после завершения первой.Таким образом, вам не нужно угадывать время выполнения, чтобы задерживать ваш код.

Promises

В es6 вы можете делать это с обещаниями, что является своего рода синтаксическим сахаромпо обратному вызову.На момент написания обещания охват браузером составлял 90% https://caniuse.com/#feat=promises

function run1(){
  console.log('1: run1')
  return new Promise(function(resolve){
    console.log('2: promise')
    setTimeout(resolve,100)
  })
}

function callback(){
  console.log('3: run2 callback')
  return new Promise(function(resolve){
    console.log('4: promise')
    setTimeout(resolve, 1000)
  })
}

function callback2(){
  console.log('5: run3 callback')
  return new Promise(function(resolve){
    console.log('6: promise')
    setTimeout(resolve, 100)
  })
}

run1()
  .then(callback()) // try to change order here, uncoment last lines...
  .then(callback2())
  // .then(callback2())
  // .then(callback())
...