Promise用法详解(一)

本文深入讲解Promise的基本概念、执行机制及如何使用Promise解决回调地狱问题,同时探讨Promise中异常捕获的不同方式及其应用场景。

Promise

基本概念
  1. Promise是一个构造函数,所以可以 new 出一个Promise的实例
  2. 在Promise上有两个函数 resolve(成功之后的回调函数)和 reject(失败后的回调函数)
  3. 在Promise构造函数的prototype属性上,有一个 .then() 方法。所以只要是Promise构造函数创建的实例,都可以访问到 .then()方法
  4. Promise表示一个异步操作,每当我们new一个Promise的实例,这个实例就代表具体的异步操作。
  5. Promise创建的实例,是一个异步操作,这个异步操作结果,只有两种结果
  • 状态1:异步执行成功,需要在内部调用成功的回调函数resolve把结果返回给调用者
  • 状态2:异步执行失败,需要在内部调用失败的回调函数reject把结果返回调用者
  • 由于Promise的实例是一个异步操作,所以内部拿到操作结果后,无法使用return把操作结果返回给调用者,这个时候只能使用回调函数的形式,把成功或失败的结果,返回给调用者
  1. 我们可以在new出来的Promise实例上,调用 .then()方法,预先为这个Promise异步操作,指定成功(resolve)和失败(reject)回调函数
形式上和具体的Promise异步操作的区别
let parmise = new Promise()

注意:上面new出来promise,只代表形式上的一个异步操作。就是说,我们只知道他是一个 异步操作,但做什么具体异步事情目前还不清楚。

let promise = new Promise(function() {
    // 这个function内部写的就是具体的异步操作
}

上面则是一个具体的异步操作,其中使用function制定一个具体的异步操作

Promise的执行时机
  • 每当new一个Promise实例的时候,除了会得到一个promise实例之外,还会立即调用我们为Promise构造函数传递的那个function,执行function中的异步代码
  • 所以在使用Promise时我们可以用函数进行包裹,使其按需执行

通过 .then()指定回调函数的时候,成功的回调函数必须传,失败的回调可以省略

有了前面的这些铺垫我们来体验一下Primise的魅力

需求 此时我们有一个简单的需求,需要去依次去读取一些文件的内容。在没有学习Promise之前我们可能这样

const fs = require('fs')
// 形参依次代表,读取路径,成功回调,失败回调
function getFileByPath(fpath, succCb, errCb) {
    fs.readFile(fpath, 'utf-8', (err, dataStr) => {
        if (err) return errCb(err)
        succCb(dataStr)
    })
}

// 依次读取
getFileByPath('./1.txt', function (data) {
    console.log(data)
    getFileByPath('./2.txt', function (data) {
        console.log(data)
        getFileByPath('./3.txt', function (data) {
            console.log(data)           
        })
    })
})

这个时候就出现了一个问题: 回调地狱
这时你想起来Pramise不就是为了来解决回调地狱的嘛,于是。

const fs = require('fs')
function getFileByPath(fpath) {
    return new Promise(function (resolve, reject) {
        fs.readFile(fpath, 'utf-8', (err, dataStr) => {
            if (err) return reject(err)
            resolve(dataStr)
       })
   })
}

// 依次读取
// 再上一个 .then中,返回一个promise实例,可以继续使用下一个 .then来处理
getFileByPath('./1.txt')
    .then(function (data) {
     console.log(data)
     return getFileByPath ('./2.txt')
 })
.then(function (data) {
    console.log(data)
    return getFileByPath('./3.txt')
})
    .then(function (data) {
    console.log(data)
})
 

也成功完成需求这里写图片描述

Promise中异常捕获两种方式的使用场景

需求 :前面的Promise执行失败,但是不要影响后续promise正常执行。

  • 此时可以单独为每个promise通过.then()指定一下失败的回调
const fs = require('fs')
function getFileByPath(fpath) {
    return new Promise(function (resolve, reject) {
        fs.readFile(fpath, 'utf-8', (err, dataStr) => {
            if (err) return reject(err)
            resolve(dataStr)
       })
   })
}

// 依次读取
// 注意此处我们写了一个根本不存在文件路径
getFileByPath('./11111111.txt')
    .then(function (data) {
     console.log(data)
     return getFileByPath ('./2.txt')
    }, function (err) {
        console.log('这是失败的结果:' + err.message)
        // return一个新的 Promise
        return getFileByPath('./2.txt')
 })
.then(function (data) {
    console.log(data)
    return getFileByPath('./3.txt')
})
    .then(function (data) {
    console.log(data)
})

结果如图这里写图片描述
需求:前面的Promise执行失败,后面Promise依赖于前面Promise执行结果,如果前面失败了后面也没有继续执行下去的意义了。

  • 此时可以使用 .catch()进行异常捕获,只要前面Promise有任何一个执行失败,立即终止所有的Promise的执行,并马上进入catch中去处理Promise中抛出的异常。
const fs = require('fs')
function getFileByPath(fpath) {
    return new Promise(function (resolve, reject) {
        fs.readFile(fpath, 'utf-8', (err, dataStr) => {
            if (err) return reject(err)
            resolve(dataStr)
       })
   })
}

// 依次读取
getFileByPath('./1.txt')
    .then(function (data) {
        console.log(data)
        // 注意此处我们写了一个根本不存在文件路径
     return getFileByPath ('./22222.txt')
    })
    .then(function (data) {
    console.log(data)
    return getFileByPath('./3.txt')
})
   .then(function (data) {
    console.log(data)
})
// catch的作用: 如果前面有任何Promise执行失败,则立即终止所有Pormise执行,并进入Promise中去处理Promise抛出的异常     
    .catch(function (err) {
    console.log("catch来捕获:" + err.message)
})

结果如图这里写图片描述

Promise 是 JavaScript 中处理异步操作的重要机制,它通过状态变化来管理异步任务的结果,并提供链式调用的能力,使得异步代码更易于理解和维护。 ### Promise 的基本结构 Promise个对象,表示个异步操作的最终完成(成功或失败)。创建Promise 时,需要传入个执行器函数,该函数有两个参数:`resolve` 和 `reject`,分别用于在操作成功或失败时通知 Promise 状态的改变[^3]。 ```javascript let promise = new Promise(function(resolve, reject) { // 异步操作 if (/* 操作成功 */) { resolve("操作成功"); } else { reject("操作失败"); } }); ``` ### Promise 的状态 Promise 有三种状态: - **Pending(进行中)**:初始状态,既不是成功也不是失败。 - **Fulfilled(已成功)**:操作成功完成,调用 `resolve` 后进入此状态。 - **Rejected(已失败)**:操作失败,调用 `reject` 后进入此状态。 旦状态改变,就不会再变,这保证了 Promise 的结果是不可变的[^3]。 ### 使用 `.then()` 和 `.catch()` Promise 的消费者通过 `.then()` 和 `.catch()` 方法来注册成功和失败的回调函数。`.then()` 接收两个参数,第个是成功回调,第二个是失败回调;`.catch()` 只处理失败的情况。 ```javascript promise .then( result => console.log("成功:" + result), error => console.log("错误:" + error) ) .catch(error => console.log("捕获错误:" + error)); ``` ### 使用 `.finally()` `.finally()` 方法用于注册个回调,在 Promise 被解决(无论是成功还是失败)后执行,常用于清理资源或执行最终操作[^4]。 ```javascript promise .then(result => console.log("成功:" + result)) .catch(error => console.log("错误:" + error)) .finally(() => console.log("运行结束")); ``` ### 链式调用与返回值 在 `.then()` 中返回个值,会自动被包装成个新的 Promise,从而实现链式调用。如果返回的是另Promise,则当前链的下个 `.then()` 会等待该 Promise 的解决[^2]。 ```javascript new Promise((resolve, reject) => { setTimeout(() => resolve(1), 1000); }) .then(result => { console.log(result); // 1 return result * 2; }) .then(result => { console.log(result); // 2 return result * 2; }) .then(result => { console.log(result); // 4 }); ``` ### 错误传播 如果在链式调用中任何步发生错误,并且没有在 `.catch()` 中处理,错误会继续向后传播,直到被捕获或导致未处理的 Promise 拒绝。 ```javascript new Promise((resolve, reject) => { throw new Error("出错了"); }) .catch(error => console.log("捕获到错误:" + error.message)) .then(() => console.log("继续执行")); ``` ### 使用 `Promise.all()` 和 `Promise.race()` - **`Promise.all(iterable)`**:等待所有 Promise 完成,如果其中任何个被拒绝,则立即拒绝。 - **`Promise.race(iterable)`**:等待第Promise 完成(无论是成功还是失败)。 ```javascript Promise.all([promise1, promise2, promise3]) .then(values => console.log(values)) .catch(error => console.log("有个失败了:" + error)); Promise.race([promise1, promise2]) .then(value => console.log("第个完成的是:" + value)); ``` ### 示例:定时任务 以下是个典型的 Promise 示例,模拟个异步定时任务: ```javascript let promise = new Promise((resolve, reject) => { setTimeout(() => { resolve("定时任务结果(resolve)"); }, 1000); }); promise .then( result => console.log("成功(then):" + result), error => console.log("错误(then):" + error) ) .finally(() => console.log("运行结束(finally)")); ```
评论 5
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值