JavaScript 异步之 Promise 写法

8,031 阅读2分钟

「这是我参与2022首次更文挑战的第29天,活动详情查看:2022首次更文挑战」。

写在前面

  • 在前面两篇文章中,我们通过嵌套回掉函数、自定义事件的方式都实现了我们的异步操作
  • 但这两种实现方式都或多或少有些不优雅
    • 嵌套回掉函数的方式在代码量增多后,会变得极其难以维护,且不能友好阅读代码
    • 自定义事件的方式,倒是比较优雅,但是为了区分不同的事件,我们需要引入额外的变量来,标识不同事件
  • 接下来,这篇文章将通过社区更加流行的 promise 写法来实现之前的例子

基于 promise 对象的改造

  • 同样的我们需要改造 move 函数
  • 既然是基于 promise 的,那么 move 函数就需要返回一个 promise 对象
  • 下面是具体实现
let move = (ele, direction, target, cb) => {
    return new Promise((resolve) => {
      let fn = () => {
        let start = parseInt(getComputedStyle(ele, null)[direction]);
        let speed = ((target - start) / Math.abs(target - start)) * 2;
        start += speed;
        ele.style[direction] = `${start}px`;

        setTimeout(() => {
          if (Math.abs(target - start) <= 2) {
            ele.style[direction] = `${target}px`;

            // cb & cb();
            resolve();
          } else {
            fn();
          }
        }, 10);
      };

      fn();
    });
};
  • 在实例化 promise 对象时,传入一个函数,其接收的则是 resolve 回掉,函数里面是 move 函数的具体处理逻辑
  • 同样的,获取 dom 元素样式,以及设置 dom 元素的样式,的方式依然不变
  • 不同的是,执行 cb 回掉函数的代码换成了 resolve 回掉
  • 表示当 dom 元素运动到终点时,就会 resolve 掉,否则继续调用 move 函数的主处理逻辑
  • 接下来看看如何使用 move 函数的
// move(ele, "left", 301, () => {
//   console.log("右移 ok");
//   move(ele, "top", 301, () => {
//     console.log("下移 ok");
//     move(ele, "left", 0, () => {
//       console.log("左移 ok");
//       move(ele, "top", 0, () => {
//         console.log("上移 ok");
//       });
//     });
//   });
// });
// promise改造:链式调用;
move(ele, "left", 300)
.then(() => {
  return move(ele, "top", 300);
})
.then(() => {
  return move(ele, "left", 0);
})
.then(() => {
  return move(ele, "top", 0);
})
.then(() => {
  console.log("完成");
});
  • 有了 promise 对象,那么我们就可以直接使用 then 方法了
  • 当前面的 promise 对象被 resolve 掉时,then 方法里面的回掉函数就会被执行,我们只用在回掉中调用 move 方法即可

小结

  • 至此,我们已经使用了三种方式去实现我们的异步操作了
  • 尽管 promise 的使用,让我们的代码,避免了嵌套回掉函数,避免了自定义事件引入额外变量
  • 但是当我们的操作步骤很多时,promise 的链式调用也会很长,多少有些不优雅
  • 那么有没有更佳,优雅的实现方式呢?
  • 下篇文章,我们将使用 async-await 去实现上面的例子

最后

  • 今天的分享就到这里了,欢迎大家在评论区里面进行讨论 👏。
  • 如果觉得文章写的不错的话,希望大家不要吝惜点赞,大家的鼓励是我分享的最大动力 🥰