Node.js中的Promise的作用与知识点讲解

Node.js中的Promise的作用与知识点讲解

在Node.js和现代JavaScript编程中,异步编程是一种常见的编程范式,它允许程序在等待某些操作完成时继续执行其他任务。Promise是处理异步操作的一种非常强大的工具,它提供了一种更加清晰和可控的方式来处理异步操作的成功和失败结果。

一. Promise的作用

Promise 是 JavaScript 中用于异步编程的一种解决方案,它代表了一个异步操作的最终完成(或失败)及其结果值。Promise 的作用主要包括以下几点:

  1. 统一异步操作的接口 :在 Promise 出现之前,JavaScript 的异步操作通常依赖于回调函数。Promise 提供了一个统一的异步操作接口,使得异步操作可以像同步操作一样通过顺序的代码来处理,这被称为"Promise 链"。

  2. 避免回调地狱 :当多个异步操作有依赖关系时,使用回调函数会导致代码嵌套多层,形成所谓的"回调地狱"。Promise 通过链式调用可以避免这种情况,使代码更加清晰。

  3. 状态一旦改变,不可再变Promise 有三种状态:pending(进行中)、fulfilled(已成功)和 rejected(已失败)。一旦 Promise 的状态从 pending 变为 fulfilled 或 rejected,这个状态就不会再改变,这有助于简化异步逻辑。

  4. 支持成功和失败的处理Promise 提供了 .then() 方法来处理异步操作成功的情况,以及 .catch() 方法来处理失败的情况。这使得错误处理变得更加集中和一致。

  5. 支持finally操作Promise 提供了 .finally() 方法,无论异步操作成功还是失败,都会执行 .finally() 中的代码,这适用于清理资源等需要在异步操作结束后执行的代码。

  6. 可以构造复杂的异步逻辑 :通过 Promise.all()Promise.race() 等方法,可以方便地构造多个异步操作的并行、竞态等复杂逻辑。

  7. 更好的错误处理 :在回调中,如果一个错误发生,它可能会被忽略,因为回调函数没有 try/catch 语句。而 Promise 可以通过链式调用的 .catch() 方法来捕获整个链中的错误。

  8. 与现代JavaScript特性集成Promise 与现代 JavaScript 的其他特性(如 async/await)集成得很好,使得异步代码可以写得更像同步代码,提高了代码的可读性和可维护性。

总的来说,Promise 提供了一种更强大、更灵活、更易于管理的方式来处理 JavaScript 中的异步操作。

二. Promise的关键知识点

Promise 是 JavaScript 中处理异步操作的核心对象,它代表了一个异步操作的最终完成(或失败)及其结果值。以下是 Promise 的一些关键知识点:

1. Promise 的状态

一个 Promise 对象有三种状态:

  • Pending(进行中):初始状态,既不是成功,也不是失败状态。
  • Fulfilled(已成功):意味着操作成功完成。
  • Rejected(已失败):意味着操作失败。

状态一旦改变,就不会再变,任何时候只能从 Pending 变为 Fulfilled 或 Rejected。

2. 创建 Promise

创建一个 Promise,你需要使用 new Promise 构造函数,并提供一个执行器函数(executor function),它带有两个参数:resolvereject

javascript 复制代码
let myPromise = new Promise((resolve, reject) => {
  // 异步操作
  if (/* 成功条件 */) {
    resolve(value); // 操作成功,调用 resolve
  } else {
    reject(reason); // 操作失败,调用 reject
  }
});

3. 使用 Promise

一旦创建了 Promise,你可以使用 .then().catch() 方法来添加处理成功的回调(成功时调用)和处理失败的回调(失败时调用)。

javascript 复制代码
myPromise
  .then(value => {
    // 成功时执行的代码
  })
  .catch(error => {
    // 失败时执行的代码
  });

4. 链式调用

Promise.then() 方法会返回一个新的 Promise,这允许链式调用。

javascript 复制代码
myPromise
  .then(result => {
    // 第一个异步操作的结果
    return anotherAsyncOperation(result);
  })
  .then(newResult => {
    // 第二个异步操作的结果
  })
  .catch(error => {
    // 任何一个异步操作失败时执行的代码
  });

5. Promise.all

当需要等待多个异步操作全部完成时,可以使用 Promise.all

javascript 复制代码
Promise.all([promise1, promise2, ...])
  .then(results => {
    // 所有 Promise 都成功时执行的代码
  })
  .catch(error => {
    // 任何一个 Promise 失败时执行的代码
  });

6. Promise.race

Promise.race 接受一个 Promise 数组作为参数,并返回一个新的 Promise,这个新的 Promise 会在数组中任何一个 Promise 完成(成功或失败)时立即完成。

javascript 复制代码
Promise.race([promise1, promise2, ...])
  .then(result => {
    // 第一个完成的 Promise 的结果
  })
  .catch(error => {
    // 第一个失败的 Promise 的错误
  });

7. Promise.resolve 和 Promise.reject

Promise.resolvePromise.reject 用于创建已经成功或失败的 Promise

javascript 复制代码
let resolvedPromise = Promise.resolve(value); // 成功的 Promise
let rejectedPromise = Promise.reject(error); // 失败的 Promise

8. async/await

asyncawait 是基于 Promise 的语法糖,它们提供了一种更简洁的方式来写异步代码。

javascript 复制代码
async function asyncFunction() {
  try {
    let result = await myPromise;
    // 使用 result
  } catch (error) {
    // 处理错误
  }
}

9. 错误处理

Promise 的错误处理非常重要。如果一个 Promise 链中没有 .catch() 方法,那么未捕获的错误可能会导致程序崩溃。

10. 微任务(Microtask)

Promise 的回调函数是在微任务队列中排队的,这意味着它们会在当前执行栈清空后,事件循环的下一阶段执行,而不是在宏任务(如 setTimeout 或 setInterval)之后。

掌握这些 Promise 的关键知识点,可以帮助你更有效地处理 JavaScript 中的异步编程问题。

三. 在项目中的应用

1. 方法1:Promise 原始用法

javascript 复制代码
/*方法1:Promise 原始用法
    前面如想取到多个sql结果,需要在每个回调函数中逐级嵌套查询
    通过Promise可以用同步的方式写异步的代码,不用层层嵌套了

    Promise 基础用法
    1.创建Promise对象  p1
*/
    const p1 = new Promise(function(resolve,reject){
       1.1 放异步任务或代码
       ...
       
       1.2返回结果
       ...
       resolve(data)  //异步任务完成的时候,调用resolve返回结果
       reject(err)    //异步任务失败的时候,调用resolve返回结果
    })

/*  2.通过then...catch获取Promise对象中的结果
    then中对应的是成功时候的结果,就是resolve返回的结果
    catch中对应的是失败时候的结果,就是reject返回的结果

    Promise 其它API 只Promise.all
    Promise.all(obj)  obj就promise对象数组,当所有的异步任务完成后,会吧结果依次放入到一个新数组中
    可以的then的回调函数中取得结果
*/
    Promise.all([p1,p2])
    .then(repaire_data=>{
        console.log(repaire_data)

        arr.push(repaire_data[0],repaire_data[1]);
        res.json({ code: 0, msg: "状态条数", data: arr });
    })
    .catch(err=>{
        console.log(err)
    })

2. 方法2:Promise 原始用法+优化

javascript 复制代码
//方法2:Promise 原始用法+优化
    const getTotalNum = (status)=>{
        return new Promise((resolve,reject)=>{
            return mysql.query(`SELECT count(id) AS total FROM reapply WHERE status = ${status}`, (error, data) => {
                if (error) {
                    reject(error)
                    console.log(error.sql);
                } else {
                    resolve(data[0]?.total)
                    // arr.push(totalNum_pass);
                }
            });
        })
    }
    Promise.all([getTotalNum(0),getTotalNum(1)])
    .then(repaire_data=>{
        console.log(repaire_data)

        arr.push(repaire_data[0],repaire_data[1]);
        res.json({ code: 0, msg: "状态条数", data: arr });
    })
    .catch(err=>{
        console.log(err)
    })

3. 方法3:Promise 原始用法+优化+async await

await 是更好的异步解决方案,更简洁。不需要用then...catch,await等待的是Promise对象里面then的结果。

用到await的函数需要async function(){}来标记。

javascript 复制代码
//方法3:Promise 原始用法+优化+async await
    const getTotalNum = (status)=>{
        return new Promise((resolve,reject)=>{
            return mysql.query(`SELECT count(id) AS total FROM reapply WHERE status = ${status}`, (error, data) => {
                if (error) {
                    reject(error)
                    console.log(error.sql);
                } else {
                    resolve(data[0]?.total)
                    // arr.push(totalNum_pass);
                }
            });
        })
    }
    // 错误处理,使用try...catch
    try{
        // 成功
        let num01 = await getTotalNum(0)
        let num02 = await getTotalNum(1)
        let num03 = await getTotalNum(2)
        let num04 = await getTotalNum(3)
        let num05 = await getTotalNum(-1)
        let num06 = await getTotalNum(-2)
        res.json({ code: 0, msg: "状态条数", data: [num01,num02,num03,num04,num05,num06] });
    }
    catch{
        // 失败
        res.json({ code: -1, msg: "状态条数", data: [] });
    }

四. 结论

Promise是Node.js和现代JavaScript中处理异步操作的强大工具。它通过提供一种结构化的方式来处理异步操作的成功和失败结果,使得代码更加清晰、易于维护,并且可以有效地并行处理多个异步操作。掌握Promise的使用,对于任何JavaScript开发者来说都是非常重要的。

相关推荐
求知若饥7 分钟前
NestJS 项目实战-权限管理系统开发(六)
后端·node.js·nestjs
jinhuazhe201311 小时前
如何解决vscode powershell乱码
ide·vscode·编辑器
理想不理想v13 小时前
webpack最基础的配置
前端·webpack·node.js
paintstar14 小时前
vscode 快速切换cangjie版本
ide·vscode·编辑器·仓颉·cangjie
科协软件201814 小时前
vscode+latex快捷键
ide·vscode·编辑器
半糖112215 小时前
【VSCode】常用插件汇总
vscode·编辑器
cnnews15 小时前
在vscode中的ESP-IDF插件中使用Arduino框架作为组件
ide·vscode·编辑器
南城巷陌15 小时前
JWT认证机制在Node.js中的详细阐述
node.js·jwt认证机制·前端安全认证
乐闻x16 小时前
VSCode 插件开发实战(三):插件配置项自定义设置
ide·vscode·编辑器