• 一篇带你看懂异步:promise、async await


    前端开发中,特别是使用Vue.js框架时,Promises(承诺)和resolve是与异步操作相关的重要概念。让我来解释一下它们的含义和如何在Vue.js中使用它们。

    一、Promise

    1. Promise(承诺):

    Promise是一种处理异步操作的对象,它表示一个可能还没有完成的操作,但在未来会完成。Promise有三个状态:pending(待定)、fulfilled(已完成)和rejected(已拒绝)。Promise允许执行异步操作并在操作完成时执行回调函数。

    2. 使用场景:

    Vue.js以及其他现代JavaScript框架广泛使用Promise来处理异步操作,如HTTP请求、定时器等。

    1. const myPromise = new Promise((resolve, reject) => {
    2. // 异步操作,例如从服务器获取数据
    3. if (/* 操作成功 */) {
    4. resolve("操作成功"); // 操作成功后调用resolve
    5. } else {
    6. reject("操作失败"); // 操作失败后调用reject
    7. }
    8. });
    9. myPromise.then((result) => {
    10. console.log(result); // 在操作成功时执行
    11. }).catch((error) => {
    12. console.error(error); // 在操作失败时执行
    13. });

    示例中,首先执行了以下部分:

    1. const myPromise = new Promise((resolve, reject) => {
    2. if (/* 操作成功 */) {
    3. // 异步操作成功后,调用resolve
    4. resolve("操作成功");
    5. } else {
    6. reject("操作失败"); // 操作失败后调用reject
    7. }
    8. });

    这部分是创建一个Promise对象,并在内部的回调函数中执行异步操作。在这个回调函数中,我们使用了resolve,表示异步操作成功。如果异步操作失败,可以使用reject 来表示操作失败。

    resolve是Promise对象内部的一个函数,用于将Promise状态从pending(待定)变为fulfilled(已完成)。reject 同理。

    接下来,我们可以使用.then().catch()来处理Promise的状态变化:

    • .then() 方法用于处理Promise对象状态从pendingfulfilled(已完成)的情况。在这个函数中,可以访问异步操作成功时的结果。

    • .catch() 方法用于处理Promise对象状态从pendingrejected(已拒绝)的情况。在这个函数中,可以访问异步操作失败时的错误信息。

    在的示例中,在异步操作成功后调用resolve来指示Promise已经成功完成,并且Promise状态变为fulfilled,将结果传递给后续的.then()回调函数,所以会执行.then()回调,打印出"操作成功"。

    如果在Promise构造函数中调用了reject,那么Promise状态会变为rejected,并且会执行.catch()回调,可以在该回调中处理异步操作的失败情况。

    3. 使用方法、场景

    第一个示例:我们创建了一个Promise实例,并将其存储在名为 myPromise 的变量中。这个Promise实例的作用域限定在当前代码块(通常是一个函数),可以在这个函数内部的任何位置使用它。例如:

    1. function myFunction() {
    2. const myPromise = new Promise((resolve, reject) => {
    3. // 异步操作,使用 resolve 或 reject
    4. });
    5. // 在函数内的任何位置都可以使用 myPromise
    6. myPromise.then((result) => {
    7. // 处理成功的情况
    8. }).catch((error) => {
    9. // 处理失败的情况
    10. });
    11. }

    在上述示例中,myPromise 是函数 myFunction 内部的一个变量,可以在函数内的任何地方使用它。

    第二个示例:get(opt) 函数返回一个新的Promise实例。这意味着每次调用 get(opt) 函数时,都会创建一个新的Promise实例。这些实例是与函数调用无关的,它们不共享状态或数据。例如:

    1. function get(opt) {
    2. return new Promise((resolve, reject) => {
    3. // 异步操作,使用 resolve 或 reject
    4. });
    5. }
    6. const promise1 = get(someOption); // 创建第一个Promise实例
    7. const promise2 = get(anotherOption); // 创建第二个Promise实例

    在上述示例中,promise1promise2 是两个不同的Promise实例,它们与函数调用无关。每个函数调用都会返回一个新的独立Promise实例。

    如果在整个系统中的多个地方都需要使用相同的Promise实例,那么第一种方法将创建一个共享的Promise实例,多处调用都将共享相同的状态和数据。这可以用于在多个地方共享相同的异步操作结果。

    而第二种方法,每次调用 get() 都会创建一个新的、独立的Promise实例,这些实例之间是相互独立的,不会共享状态或数据。这适用于需要在不同地方使用不同的异步操作的情况。

    如果需要在多个地方共享相同的异步操作结果,第一种方法可能更合适。如果需要在不同地方使用独立的异步操作,第二种方法更适合。

    4.Promise的链式写法

    Promise的链式写法是一种结构化的方式,用于在处理异步操作时按顺序执行一系列操作。这种写法可以让清晰地组织和控制异步操作的流程。在这种写法中,通过使用.then()方法将多个回调函数链接在一起,每个回调函数返回一个新的Promise对象,从而允许顺序执行多个异步操作。

    一个典型的Promise链式写法如下:

    1. someAsyncFunction()
    2. .then((result1) => {
    3. // 处理 result1,可以返回一个新的Promise
    4. return someOtherAsyncFunction(result1);
    5. })
    6. .then((result2) => {
    7. // 处理 result2,可以返回一个新的Promise
    8. return anotherAsyncFunction(result2);
    9. })
    10. .then((result3) => {
    11. // 处理 result3
    12. })
    13. .catch((error) => {
    14. // 处理任何发生的错误
    15. });

    在上面的示例中,首先调用了someAsyncFunction(),然后通过.then()方法将多个回调函数连接在一起,每个.then()回调接受上一个.then()回调的结果并返回一个新的Promise。这允许按顺序执行异步操作,并且每个.then()中的操作都可以处理前一个操作的结果。

    如果任何地方发生了错误,它将被捕获并传递给.catch()块进行处理。

    链式写法的好处在于它使异步操作的顺序和控制更加明确,而不需要嵌套回调,从而提高了可读性和维护性。这种结构也使你能够有效地处理异步操作之间的依赖关系,因为每个.then()中的操作依赖于前一个操作的结果。

    在Promise的链式写法中,通常不需要显式地传递(resolve, reject),因为.then().catch() 方法会自动处理Promise的状态和结果。这是Promise的一种抽象方式,它隐藏了底层的resolvereject

    在链式写法中,.then() 方法用于处理Promise的成功状态,而 .catch() 方法用于处理Promise的失败状态。这两个方法接收一个回调函数作为参数,这个回调函数会自动接收前一个Promise的结果或错误。如果前一个Promise成功,.then()回调将被执行,如果前一个Promise失败,.catch()回调将被执行。例如:

    1. someAsyncFunction()
    2. .then((result) => {
    3. // 这个回调处理成功状态
    4. console.log(result);
    5. })
    6. .catch((error) => {
    7. // 这个回调处理失败状态
    8. console.error(error);
    9. });

    二、async await

    1)当谈到JavaScript中的异步编程时,async/await 是一种非常强大和直观的方法。它是在ECMAScript 2017 (ES8) 中引入的,用于简化Promise的使用和管理异步操作。

    1. async 函数

    • async 函数是一个特殊的函数关键字,它用于声明一个异步函数。异步函数将始终返回一个Promise对象。
    • 异步函数可以包含 await 表达式,以等待其他异步操作完成。

    示例:

    1. async function fetchData() {
    2. // 异步操作
    3. }

    2. await 表达式

    • await 只能在 async 函数内部使用,它用于等待一个Promise解决为其值。
    • await 将暂停函数的执行,直到等待的Promise完成(无论成功或失败)并返回结果。

    示例:

    1. async function fetchAndProcessData() {
    2. const data = await fetchData(); // 等待fetchData()的完成
    3. // 在这里可以使用data
    4. }

    3. 错误处理

    • 使用try/catch来捕获await表达式引发的错误。
    • 可以使用普通的同步错误处理机制来处理async/await中的错误。

    示例:

    1. async function fetchAndProcessData() {
    2. try {
    3. const data = await fetchData();
    4. // 处理成功情况
    5. } catch (error) {
    6. // 处理错误情况
    7. }
    8. }

    4. 并行操作

    • 使用多个await表达式可以在某种程度上实现并行操作,等待多个异步操作同时完成。
    • 这可以提高性能,但要注意不要过度并行,以避免不必要的竞争条件。

    示例:

    1. async function fetchAndProcessData() {
    2. const result1 = await fetchFirstData();
    3. const result2 = await fetchSecondData();
    4. // result1和result2将顺序完成
    5. }

    5. 顺序执行

    • async/await 确保异步操作按照它们的声明顺序执行,从而更容易理解和维护异步代码。

    示例:

    1. async function fetchAndProcessData() {
    2. const result1 = await fetchFirstData();
    3. const result2 = await process(result1);
    4. const result3 = await fetchSecondData(result2);
    5. // 每个操作都在前一个操作完成后执行
    6. }

    2)当涉及到异步编程时,async/await 在许多常见场景中都非常有用。以下是一些常用场景:

    1. 发起网络请求async/await 可以用于发起HTTP请求,等待响应,并处理返回的数据。这对于处理API调用、获取远程数据等非常有用。

    1. async function fetchData() {
    2. try {
    3. const response = await fetch('https://api.example.com/data');
    4. const data = await response.json();
    5. // 处理返回的数据
    6. } catch (error) {
    7. // 处理错误
    8. }

    2. 文件操作:在Node.js中,async/await 可以用于执行文件读取、写入等操作。这使得处理文件系统操作更加方便。

    1. const fs = require('fs').promises;
    2. async function readFile() {
    3. try {
    4. const content = await fs.readFile('file.txt', 'utf-8');
    5. // 处理文件内容
    6. } catch (error) {
    7. // 处理错误
    8. }

    3. 循环操作async/await 可以用于按顺序处理循环中的项目,确保每个项目的处理都完成后再进行下一个。

    1. async function processItems(items) {
    2. for (const item of items) {
    3. const result = await processItem(item);
    4. // 处理每个项目的结果
    5. }

    4. 多个并行操作:通过使用 Promise.all 结合 async/await,可以实现多个并行异步操作,以提高性能。

    1. async function parallelOperations() {
    2. const results = await Promise.all([
    3. asyncOperation1(),
    4. asyncOperation2(),
    5. asyncOperation3()
    6. ]);
    7. // 处理所有操作的结果

    5. 错误处理async/await 简化了错误处理,通过 try/catch 可以捕获异步操作中的错误。

    1. async function someAsyncTask() {
    2. try {
    3. // 异步操作
    4. } catch (error) {
    5. // 处理错误
    6. }

    三、promise和async await

    能用async await的地方也能用promise的链式写法

    await后面的代码相当于then的回调,也就是微任务,加入微任务队列,然后js继续执行其他代码,等到同步任务执行完了再去微任务队列取出来(先进先出原则)。

    1. async关键字用于修饰函数,被它修饰的函数,一定返回Promise。

    2. await 关键字表示等待某个Promise完成,它必须用于 async 函数中。

  • 相关阅读:
    2.7 数组
    笔试强训(三十七)
    二、nginx URL重写[rewrite]
    vue项目集成萤石云在Web系统中实现实时摄像头监控及控制功能
    【Java并发编程七】Java内存模型
    口袋参谋:如何对宝贝关键词进行词根分析?用它就对了!
    Java加密算法有几种?
    IP分片、TCP分段
    软件代码签名证书怎么申请
    Ubuntu:安装docker
  • 原文地址:https://blog.csdn.net/coinisi_li/article/details/133762171