前端Vue日常工作中--Promise

前端Vue日常工作中--Promise

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

1.基本说明

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

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

1.1Promise 的基本结构

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

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

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

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

1.2Promise 的状态转换

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

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);
  });

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

1.7使用 Promise.resolve 和 Promise.reject

Promise.resolvePromise.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 提供了一种链式调用的方式,使得异步操作的代码更具可读性。通过使用 thencatch 方法,可以清晰地处理异步操作的成功和失败情况。

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

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

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

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

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

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

相关推荐
小岛前端6 分钟前
展示!我 Vibe 了一个 Codex HUD
前端·ai编程
我是大卫21 分钟前
【图】React源码解析-从源码数据结构、执行机制对比、闭包陷阱与最佳实践四个维度,深挖useMemo和useCallback的底层原理
前端·react.js·源码
霸道流氓气质22 分钟前
SpringBoot+Vue通过ModbusTCP协议实现PLC 设备连接、重连实时控制
vue.js·spring boot·后端
不一样的少年_22 分钟前
不用 LangChain,手搓 AI Agent:给大模型装上“手”,让它自己读项目文件
前端·人工智能·agent
索西引擎24 分钟前
【React】useState 函数式更新机制:闭包陷阱规避与状态一致性保障分析
前端·react.js·前端框架
anyup32 分钟前
从文本到具身:我给 AI Agent 搭了套实时 3D 交互身体
前端·人工智能·aigc
lichenyang45334 分钟前
给弱模型一本说明书:我把文档规范做成单文件 Skill,也终于分清了 Skill 和 MCP
前端
咖啡无伴侣44 分钟前
Vue3 DOM 异步更新与性能优化全套学习笔记
前端·vue.js
sugar__salt1 小时前
Vue3 基础知识点整理 —— 从入门到响应式核心完全指南
vue.js·笔记·vue·vue3
为了摸鱼而战1 小时前
OpenSpec + Superpowers + gstack 三器合一:你的 AI 编程终于可以从"拍脑袋"进化到"流水线"了
前端