前端Vue日常工作中--Promise

前端Vue日常工作中--Promise

Promise 是 JavaScript 中用于处理异步操作的一种机制,它的主要目的是更好地组织和管理异步代码。Promise 对象有三个状态:pending(进行中)、fulfilled(已成功)和 rejected(已失败)。一旦 Promise 的状态变为 fulfilled 或 rejected,就称为 Promise 已经 settled(已定型),这时可以通过 then 方法来处理对应的状态。

1.基本说明

一个 Promise 可以处于以下三种状态之一:

  • Pending(进行中): 初始状态,表示异步操作还在进行中,未完成。
  • Fulfilled(已成功): 表示异步操作成功完成,此时会调用 resolve 函数,并将结果传递给成功的处理函数。
  • Rejected(已失败): 表示异步操作失败,此时会调用 reject 函数,并将错误信息传递给失败的处理函数。

1.1Promise 的基本结构

一个 Promise 对象可以通过 new Promise() 来创建,其构造函数接受一个带有 resolve 和 reject 两个参数的函数,表示异步操作的结果。

javascript 复制代码
const myPromise = new Promise((resolve, reject) => {
  // 异步操作,例如网络请求、定时器等

  // 异步操作成功时调用 resolve
  resolve('Success!');

  // 异步操作失败时调用 reject
  // reject('Error!');
});

1.2Promise 的状态转换

Promise 的状态是可以从 pending 转变为 fulfilled 或 rejected 的,但一旦转变了就不可再变。

javascript 复制代码
// 创建一个 pending 状态的 Promise 对象
const myPromise = new Promise((resolve, reject) => {
  // 异步操作,例如网络请求、定时器等

  // 异步操作成功时调用 resolve
  resolve('Success!');

  // 异步操作失败时调用 reject
  // reject('Error!');
});

// 使用 then 处理成功的情况
myPromise.then((result) => {
  console.log(result); // 输出: Success!
});

// 使用 catch 处理失败的情况
myPromise.catch((error) => {
  console.error(error); // 输出: Error!
});

1.3Promise 链式调用

Promise 提供了链式调用的方式,通过 then 方法可以在一个 Promise 的成功状态处理函数中返回另一个 Promise,实现连续的异步操作。

javascript 复制代码
const myPromise = new Promise((resolve, reject) => {
  // 异步操作,例如网络请求、定时器等
  resolve('Step 1');
});

myPromise
  .then((result) => {
    console.log(result); // 输出: Step 1
    return 'Step 2';
  })
  .then((result) => {
    console.log(result); // 输出: Step 2
    throw new Error('Error in Step 2');
  })
  .catch((error) => {
    console.error(error.message); // 输出: Error in Step 2
  });

then 方法返回的是一个新的 Promise,这使得我们可以通过链式调用来处理连续的异步操作。

1.4Promise.all 和 Promise.race

Promise.all 可以接受一个 Promise 数组,并在所有 Promise 都成功时返回一个包含所有结果的数组,任何一个 Promise 失败则直接触发失败。

javascript 复制代码
const promise1 = Promise.resolve('One');
const promise2 = new Promise((resolve) => setTimeout(() => resolve('Two'), 2000));
const promise3 = Promise.reject(new Error('Three'));

Promise.all([promise1, promise2, promise3])
  .then((results) => {
    console.log(results); // 任何一个 Promise 失败都不会执行到这里
  })
  .catch((error) => {
    console.error(error.message); // 输出: Three
  });

Promise.race 则在第一个 Promise 变为 settled(已定型)时返回它的结果或错误,无论是成功还是失败。

javascript 复制代码
const promise1 = new Promise((resolve) => setTimeout(() => resolve('One'), 3000));
const promise2 = new Promise((resolve) => setTimeout(() => resolve('Two'), 2000));

Promise.race([promise1, promise2])
  .then((result) => {
    console.log(result); // 输出: Two
  })
  .catch((error) => {
    console.error(error.message); // 不会执行到这里
  });

1.5Promise 的错误处理

catch 方法可以来处理 Promise 异步操作失败的情况。此外,还可以在 then 方法中的第二个参数中处理失败的情况,这样可以更灵活地分别处理成功和失败的结果。

javascript 复制代码
const myPromise = new Promise((resolve, reject) => {
  // 异步操作,例如网络请求、定时器等
  reject(new Error('Failed!'));
});

myPromise
  .then(
    (result) => {
      console.log(result); // 不会执行到这里
    },
    (error) => {
      console.error(error.message); // 输出: Failed!
    }
  );

1.6异步任务的串行执行

Promise 的串行执行是通过链式调用 then 方法来实现的。每个 then 方法都返回一个新的 Promise 对象,使得可以依次串联多个异步任务。

javascript 复制代码
const asyncTask1 = () => {
  return new Promise((resolve) => {
    setTimeout(() => {
      console.log('Async Task 1');
      resolve('Task 1 Result');
    }, 1000);
  });
};

const asyncTask2 = () => {
  return new Promise((resolve) => {
    setTimeout(() => {
      console.log('Async Task 2');
      resolve('Task 2 Result');
    }, 500);
  });
};

asyncTask1()
  .then((result1) => {
    console.log(result1);
    return asyncTask2();
  })
  .then((result2) => {
    console.log(result2);
  });

asyncTask2 在 asyncTask1 执行成功后才会执行,实现了异步任务的串行执行。

1.7使用 Promise.resolve 和 Promise.reject

Promise.resolve 和 Promise.reject 是两个快捷方法,用于创建已经定型的 Promise 对象。

javascript 复制代码
const resolvedPromise = Promise.resolve('Resolved Data');
const rejectedPromise = Promise.reject(new Error('Rejected Error'));

resolvedPromise.then((data) => console.log(data)); // 输出: Resolved Data
rejectedPromise.catch((error) => console.error(error.message)); // 输出: Rejected Error

1.8async/await 与 Promise 结合使用

ES2017 引入了 async/await 语法,它建立在 Promise 的基础上,提供一种更清晰、更同步化的方式来处理异步操作。

javascript 复制代码
async function fetchData() {
  try {
    const result1 = await asyncTask1();
    console.log(result1);

    const result2 = await asyncTask2();
    console.log(result2);
  } catch (error) {
    console.error(error.message);
  }
}

fetchData();

async/await 使得异步代码看起来更像同步代码,提高了代码的可读性。

2.父子组件中使用

在Vue中,父子组件之间的通信可以使用Promise来实现异步操作的协调。在父组件中调用子组件的方法,并使用Promise来处理异步操作:

父组件

html 复制代码
<template>
  <div>
    <h1>Parent Component</h1>
    <button @click="getDataFromChild">Get Data from Child</button>
    <Child ref="childComponent"></Child>
  </div>
</template>

<script>
import Child from './Child.vue';

export default {
  components: {
    Child,
  },
  methods: {
    getDataFromChild() {
      // 调用子组件的方法,并返回一个Promise对象
      const promiseFromChild = this.$refs.childComponent.getChildData();

      promiseFromChild.then((data) => {
        console.log('Data received from child:', data);
      }).catch((error) => {
        console.error('Error from child:', error);
      });
    },
  },
};
</script>

子组件

html 复制代码
<template>
  <div>
    <h2>Child Component</h2>
  </div>
</template>

<script>
export default {
  methods: {
    getChildData() {
      // 模拟异步操作,例如网络请求
      return new Promise((resolve, reject) => {
        setTimeout(() => {
          const data = 'Data from child component';
          // 成功时调用resolve,将数据传递给父组件
          resolve(data);
          
          // 如果异步操作失败,调用reject
          // reject(new Error('Error in child component'));
        }, 2000);
      });
    },
  },
};
</script>

父组件包含一个按钮,点击按钮后会调用 子组件的 getChildData 方法。getChildData 方法返回一个Promise对象,通过setTimeout模拟了一个异步操作。当异步操作完成时,会调用resolve方法,将数据传递给父组件。

父组件通过 then 方法处理异步操作成功的情况,通过 catch 方法处理异步操作失败的情况。通过Promise来实现父子组件的异步通信,可以更好地管理异步代码,提高代码的可读性和可维护性。

3.Promise作用总结

Promise 在 JavaScript 中的作用主要是用于处理异步操作,提供了一种更结构化、更可读的方式来编写异步代码。

  1. 更清晰的异步代码: Promise 提供了一种链式调用的方式,使得异步操作的代码更具可读性。通过使用 then 和 catch 方法,可以清晰地处理异步操作的成功和失败情况。

  2. 避免回调地狱: 传统的回调函数嵌套容易导致回调地狱(callback hell),代码难以阅读和维护。Promise 的链式调用可以避免这种情况,使得异步代码更加结构化。

  3. 更好的错误处理: Promise 提供了 catch 方法来专门处理异步操作中的错误,使得错误处理更为集中和清晰。而且可以使用 finally 方法在不管 Promise 是成功还是失败的情况下执行一段代码。

  4. 异步操作的状态管理: Promise 有三种状态(pending、fulfilled、rejected),这种状态管理使得异步操作更加可控。一旦 Promise 的状态变为 fulfilled 或 rejected,就称为 Promise 已经 settled(已定型)。

  5. 方便的异步串行执行: 通过链式调用 then 方法,可以实现异步任务的串行执行,使得异步操作按照特定的顺序执行,而不是并发执行。

  6. Promise.all 和 Promise.race: 提供了 Promise.all 和 Promise.race 两个方法,用于处理多个异步操作。Promise.all 在所有 Promise 都成功时返回一个包含所有结果的数组,而 Promise.race 在第一个 Promise 变为 settled(已定型)时返回它的结果或错误。

  7. 更好的异步错误堆栈信息: 使用 Promise,可以更方便地追踪异步错误的来源,因为错误会被传递到 catch 方法,而不会被隐式地丢失。

相关推荐
花开盛夏^.^7 小时前
电脑打开多个浏览器Web窗口占用较大的运行内存的原因
前端·浏览器
馒头不想说话8 小时前
实体店老板的24小时AI运营员工,写、剪、发全自动,省下一整个团队工资
前端
椒哥10 小时前
一天被问几十次"允许",我统计了 517 次,然后写了个插件
前端·javascript·github
风骏时光牛马10 小时前
生成一个AI稳定性治理及疑难问题分析标题,只需要一个标题,不需要其他的任何文本。
前端
莫西干式秃头11 小时前
用 AI + threejs 写了个浏览器里的 3D 动作游戏《武来》:砍怪、放技能、开 SU7
前端·人工智能·three.js
kyriewen11 小时前
我测了 6 种防请求竞态的写法:只有 1 种真能打
前端·javascript·程序员
孟健11 小时前
用 WorkBuddy 做个人名片网页,挂上开源设计技能后效果完全不同了
前端·人工智能·ai编程
IT_陈寒11 小时前
SpringBoot自动配置的坑,这次终于爬出来了
前端·人工智能·后端
LuHang12 小时前
从天地图切换到高德地图:一次真实的底图迁移实战
前端·vue.js·cesium
用户3600555790012 小时前
Kestrel_VLLM - 27 · 寄存器常驻与融合发射:两次「少发一次」
前端