2.8.JavaScript异步流程控制-async+await

942 阅读1分钟

async+await(终极异步编程解决方案)

1. async+await 好处

  1. 解决了callback回调问题(回调地狱);
  2. 可以使用tryCatch捕获错误异常
  3. 让代码执行的更像同步执行
  4. await要搭配async来使用

2. 异步的四种方式比较(事件依次执行)

  1. 回调函数(回调地狱)
  2. Promise
  3. generator+co * 用的时候 yield 暂停
  4. async+await

1.回调函数

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <title>事件依次执行</title>
  <style>
    html * {
      padding: 0;
      margin: 0;
    }
    .balls .ball {
      background: red;
      position: absolute;
      border-radius: 50%;
      width: 100px;
      height: 100px;
    }
    .balls .ball1 {
      top: 20px;
      left: 0px;
    }
    .balls .ball2 {
      top: 140px;
      left: 0;
    }
    .balls .ball3 {
      top: 260px;
      left: 0;
    }
  </style>
</head>
<body>
  <section>
    <dl class="balls">
      <dd class="ball ball1"></dd>
      <dd class="ball ball2"></dd>
      <dd class="ball ball3"></dd>
    </dl>
  </section>
  <script>
    let $ = document.querySelector.bind(document);
    function move(ele, target, callback) {
      let left = 0;
      let timer = setInterval(function () {
        if (left >= target) {
          clearInterval(timer);
          return callback();
        }
        left++;
        ele.style.left = left + 'px';
      }, 6)
    }
    move($('.ball1'), 500, function () {
      move($('.ball2'), 300, function () {
        move($('.ball3'), 200, function () {
          console.log('ok')
        })
      })
    })
  </script>
</body>
</html>

2. Promise

let $ = document.querySelector.bind(document);
function move(ele, target) {
  return new Promise((resolve, reject) => {
    let left = 0;
    let timer = setInterval(function () {
      if (left >= target) {
        clearInterval(timer);
        return resolve();
      }
      left++;
      ele.style.left = left + 'px';
    }, 6)
  })
}
move($('.ball1'), 500).then(() => {
  return move($('.ball2'), 300)
}).then(() => {
  return move($('.ball3'), 100)
}).catch((err) => {
  console.log(err)
})

3. generator+co

let $ = document.querySelector.bind(document);
function move(ele, target) {
  return new Promise((resolve, reject) => {
    let left = 0;
    let timer = setInterval(function () {
      if (left >= target) {
        clearInterval(timer);
        return resolve();
      }
      left++;
      ele.style.left = left + 'px';
    }, 6)
  })
}
function* gen() {
  let a = yield move($('.ball1'), 500);
  console.log(a);
  let b = yield move($('.ball2'), 300);
  console.log(b);
  let c = yield move($('.ball3'), 100);
  console.log(c);
  return undefined;
}
let it = gen();
let i = 0;
function co(it) {
  return new Promise((resolve, reject) => {
    function next(val) {
      let { value, done } = it.next(val);
      if (!done) {
        value.then(() => {
          next(++i);
        })
      } else {
        resolve('完成');
      }
    }
    next();
  })
}
co(gen()).then((data) => {
  console.log(data);
})

4. async+await

let $ = document.querySelector.bind(document);
function move(ele, target) {
  return new Promise((resolve, reject) => {
    let left = 0;
    let timer = setInterval(function () {
      if (left >= target) {
        clearInterval(timer);
        return resolve();
      }
      left++;
      ele.style.left = left + 'px';
    }, 6)
  })
}
async function m() {
  await move($('.ball1'), 500);
  await move($('.ball2'), 300);
  await move($('.ball3'), 100);
  return '完成';
}
m().then(function (data) {
  console.log(data)
})