Promise(简介、基本使用、API、手写实现 Promise、async与await)(二)

简介: Promise(简介、基本使用、API、手写实现 Promise、async与await)(二)

3.4 Promise.resolve 方法

Promise.resolve 方法: (value) => {}
  • value: 成功的数据或 promise 对象

返回一个成功/失败的 promise 对象

// 如果传入的参数为 非Promise类型的对象, 则返回的结果为成功promise对象
    const p1 = Promise.resolve( 123 )
    console.log(p1)
    // 如果传入的参数为 Promise 对象, 则参数的结果决定了 resolve 的结果
    const p2 = Promise.resolve( new Promise( (resolve, reject)=>{
      resolve('ok')
    } ) ) 
    console.log(p2);
    const p3 = Promise.resolve( new Promise( (resolve, reject)=>{
      reject('error')
    } ) ) 
    console.log(p3);

3.5 Promise.reject 方法

Promise.reject 方法: (reason) => {}
  • reason: 失败的原因

返回一个失败的 promise 对象

const p1 = Promise.reject( new Promise((resolve, reject)=>{
      resolve('ok')
    }) )
    console.log(p1)

3.6 Promise.all 方法

Promise.all 方法: (promises) => {}
  • promises: 包含 n 个 promise 的数组

返回一个新的 promise, 只有所有的 promise 都成功才成功, 只要有一个失败了就直接失败

const p1 = Promise.resolve('OK')
    const p2 = Promise.reject('Error')
    // 处理失败,防止报错
    p2.catch( reason=>{} )
    const p3 = new Promise( (resolve, reject)=>{
      resolve('ok')
    } )
    // p1 p3 的状态为成功,p2 为失败,res1的状态为失败
    const res1 = Promise.all( [p1, p2, p3] )
    // 处理失败,防止报错
    res1.catch( reason=>{} )
    // p1 p3 的状态为成功,res2的状态为成功
    const res2 = Promise.all( [p1, p3] )
    console.log( res1 )
    console.log( res2 )

3.7 Promise.race 方法

Promise.race 方法: (promises) => {}
  • promises: 包含 n 个 promise 的数组

返回一个新的 promise, 第一个完成的 promise 的结果状态就是最终的结果状态

const p1 = new Promise((resolve, reject) => {
        setTimeout(() => {
          resolve('ok')
        }, 1000)
      })
      const p2 = Promise.resolve('ok')
      const p3 = Promise.reject('err')
      const res = Promise.race([p1, p2, p3])
      console.log(res)

第一个完成的Promise为 p2

p2状态为成功,最后结果为成功

4. promise 的几个关键问题

4.1 如何改变 promise 的状态

  • (1) resolve(value): 如果当前是 pending 就会变为 resolved
  • (2) reject(reason): 如果当前是 pending 就会变为 rejected
  • (3) 抛出异常: 如果当前是 pending 就会变为 rejected
let p = new Promise( (resolve, reject)=>{
      resolve('ok')
    } )
    // resolve -- 成功
    console.log(p)
    p = new Promise( (resolve, reject)=>{
      reject('ok')
    } )
    // reject -- 失败
    console.log(p)
    p = new Promise( (resolve, reject)=>{
      throw 'err'
    } )
    // 抛出错误为失败
    console.log(p)

4.2 一个 promise 指定多个成功/失败回调函数

一个 promise 指定多个成功/失败回调函数, 都会调用吗?

  • 当 promise 改变为对应状态时都会调用
let p = new Promise((resolve, reject) => {
        resolve('OK');
      })
    // 状态为成功,后面的成功的回调函数都会被调用
      p.then( val=>{
        console.log('成功的回调函数')
      } )
      p.then( val=>{
        console.log('成功的回调函数')
      } )
      p.then( val=>{
        console.log('成功的回调函数')
      } )

4.3 改变 promise 状态和指定回调函数谁先谁后

  • (1) 都有可能, 正常情况下是先指定回调再改变状态, 但也可以先改状态再指定回调
  • (2) 如何先改状态再指定回调?
  • ① 在执行器中直接调用 resolve()/reject()
  • ② 延迟更长时间才调用 then()
  • 看回调函数在执行器中调用的时间
  • (3) 什么时候才能得到数据?
  • ① 如果先指定的回调, 那当状态发生改变时, 回调函数就会调用, 得到数据
  • ② 如果先改变的状态, 那当指定回调时, 回调函数就会调用, 得到数据
  • 回调函数调用, 得到数据
// 先指定回调函数
      // 再改变状态
      // 执行器中的执行的为异步任务,调用回调函数在1秒后
      let p = new Promise((resolve, reject) => {
        setTimeout(() => {
          resolve('OK')
        }, 1000)
      })
      p.then(
        (value) => {
          console.log(value)
        },
        (reason) => {}
      )
      // 先改变状态
      // 执行器内为同步任务
      // 执行执行器就立马调用成功的回调函数
      // 先改变状态在指定回调函数
      p = new Promise((resolve, reject) => {
        resolve('OK')
      })
      p.then(
        (value) => {
          console.log(value)
        },
        (reason) => {}
      )

4.4 promise.then()返回的新 promise 的结果状态

promise.then()返回的新 promise 的结果状态由什么决定?

  • (1) 简单表达: 由 then()指定的回调函数执行的结果决定
  • (2) 详细表达:
  • ① 如果抛出异常, 新 promise 变为 rejected, reason 为抛出的异常
  • ② 如果返回的是非 promise 的任意值, 新 promise 变为 resolved, value 为返回的值
  • ③ 如果返回的是另一个新 promise, 此 promise 的结果就会成为新 promise 的结果
// 1
      let p = new Promise((resolve, reject) => {
        resolve('ok')
      })
      let res = p.then(
        (val) => {
          throw 'err'
        },
        (reason) => {}
      )
      console.log(res)
      // 2
      p = new Promise((resolve, reject) => {
        resolve('ok')
      })
      res = p.then(
        (val) => {
          return 123
        },
        (reason) => {}
      )
      console.log(res)
      // 3
      p = new Promise((resolve, reject) => {
        resolve('ok')
      })
      res = p.then(
        (val) => {
          return new Promise.reject('Err')
        },
        (reason) => {}
      )
      console.log(res)

4.5 promise 串连多个操作任务(链式调用)

  • (1) promise 的 then()返回一个新的 promise, 可以开成 then()的链式调用
  • (2) 通过 then 的链式调用串连多个同步/异步任务
let p = new Promise((resolve, reject) => {
        resolve('ok')
      })
      p.then((val) => {
        return new Promise((resolve, reject) => {
          resolve('OK')
        })
      })
        .then((val) => {
          console.log(val)
        })
        .then((val) => {
          // 上一个then结果集中没有返回值,结果集为undefined
          // 输出为undefined
          console.log(val)
        })

4.6 promise 异常传透

  • (1) 当使用 promise 的 then 链式调用时, 可以在最后指定失败的回调,
  • (2) 前面任何操作出了异常, 都会传到最后失败的回调中处理
let p = new Promise((resolve, reject) => {
        resolve('ok')
      })
      p.then( val=>{
        throw 'err'
      } ).then( val=>{
        console.log(222);
      } ).then( val=>{
        console.log(222);
      } ).catch( reason=>{
        console.log(reason)
      } )

出错之后直接到catch,中的其他then不执行

4.7 中断 promise 链

  • (1) 当使用 promise 的 then 链式调用时, 在中间中断, 不再调用后面的回调函数
  • (2) 办法: 在回调函数中返回一个 pendding 状态的 promise 对象 (有且只有一个方式)
let p = new Promise((resolve, reject) => {
            setTimeout(() => {
                resolve('OK');
            }, 1000);
        });
        p.then(value => {
            console.log(111);
            //有且只有一个方式
            // 新创建的Promise对象,且没有调用回调函数,或抛出错误
            // 对象的状态没有改变
            // 所以该Promise对象的状态为pending
            // 下面的then,catch定义的为失败或成功的回调函数
            // 所以会中断退出,不会继续向下执行
            return new Promise(() => {});
        }).then(value => {
            console.log(222);
        }).then(value => {
            console.log(333);
        }).catch(reason => {
            console.warn(reason);
        });

5. 自定义手写实现 Promise

5.1 定义整体结构

// 定义Promise的构造函数
function Promise(excutor) {
}
// 定义Promise的then函数
// 定义在prototype上
Promise.prototype.then = function () {
}

官方的 Promise 的实例化对象的 then 等函数都在其原型链上,所以自定义的 Promise 的 then 等函数也挂在原型链上。

5.2 Promise 构造函数的实现

// 定义Promise的构造函数
function Promise(excutor) {
  // 在执行构造函数时会同步立即执行执行器函数
  // 调用传参传过来的执行器函数
  // 执行器函数中有两个参数,resolve函数与reject函数
  // 执行执行器函数需要传入两个参数,resolve函数与reject函数
  excutor(resolve, reject)
}

5.2.1 resolve与reject结构搭建

// 定义Promise的构造函数
function Promise(excutor) {
  // 执行器函数执行过程中会调用resolve或reject函数改变Promise的状态
  // resolve与reject函数需要定义
  // 定义resolve函数
  // 会传递过来一个参数,用于改变Promise的结果值 PromiseResult
  function resolve(data) {
  }
  // 定义reject函数
  // 会传递过来一个参数,用于改变Promise的结果值 PromiseResult
  function reject(data) {
  }
  // 调用传参传过来的执行器函数
  excutor(resolve, reject)
}

5.2.2 resolve与reject函数实现

// 定义Promise的构造函数
function Promise(excutor) {
  // resolve函数与reject函数改变 Promise的状态 PromiseState 和 Promise的结果 PromiseResult
  // PromiseState PromiseResult 每个 Promise 对象都有,所以定义在构造函数中
  this.PromiseState = 'pending' // 默认状态 pending
  this.PromiseResult = null // 结果默认为空
  // 定义resolve函数
  function resolve(data) {
    // 修改 Promise的状态 PromiseState 为成功 fulfilled/resolved
    this.PromiseState = 'fulfilled'
    // 修改 Promise的结果 PromiseResult 为 data
    this.PromiseResult = data
  }
  // 定义reject函数
  function reject(data) {
    // 修改 Promise的状态 PromiseState 为成功 rejected
    this.PromiseState = 'rejected'
    // 修改 Promise的结果 PromiseResult 为 data
    this.PromiseResult = data
  }
  // 调用传参传过来的执行器函数  同步调用
  excutor(resolve, reject)
}

5.2.3 throw抛出错误改变状态

// 定义Promise的构造函数
function Promise(excutor) {
  // 定义 PromiseState PromiseResult 
  this.PromiseState = 'pending' // 默认状态 pending
  this.PromiseResult = null // 结果默认为空
  // 定义resolve函数
  function resolve(data) {
    this.PromiseState = 'fulfilled' // 修改 Promise的状态 PromiseState
    this.PromiseResult = data       // 修改 Promise的结果 PromiseResult
  }
  // 定义reject函数
  function reject(data) {
    this.PromiseState = 'rejected'  // 修改 Promise的状态 PromiseState
    this.PromiseResult = data       // 修改 Promise的结果 PromiseResult
  }
  // 异常在 excutor 中抛出的
  // 捕获 excutor 中的异常并进行处理
  try {
    // 调用传参传过来的执行器函数  同步调用
    excutor(resolve, reject)
  } catch(e) {
    // 处理异常
    // 改变Promise状态为失败,改变结果
    // 直接调用 reject 函数 传入失败信息
    reject(e)
  }
}

5.2.3 状态只能修改一次

Promise 的状态只能修改一次,只能从 pending 到成功或从 pending 到失败,没有其他可能的改变

// 定义Promise的构造函数
function Promise(excutor) {
  // 定义 PromiseState PromiseResult 
  this.PromiseState = 'pending' // 默认状态 pending
  this.PromiseResult = null // 结果默认为空
  // 定义resolve函数
  function resolve(data) {
    // 状态只能修改一次
    // 如果状态已经修改了(即不为pending)就直接退出
    if (this.PromiseState !== 'pending') return;
    this.PromiseState = 'fulfilled' // 修改 Promise的状态 PromiseState
    this.PromiseResult = data       // 修改 Promise的结果 PromiseResult
  }
  // 定义reject函数
  function reject(data) {
    // 状态只能修改一次
    // 如果状态已经修改了(即不为pending)就直接退出
    if (this.PromiseState !== 'pending') return;
    this.PromiseState = 'rejected'  // 修改 Promise的状态 PromiseState
    this.PromiseResult = data       // 修改 Promise的结果 PromiseResult
  }
  // 捕获 excutor 中的异常并进行处理
  try {
    // 调用传参传过来的执行器函数  同步调用
    excutor(resolve, reject)
  } catch (e) {
    // 处理异常,改变Promise状态为失败,改变结果
    reject(e)
  }
}


相关文章
|
2月前
|
前端开发 安全 JavaScript
Promise 这个新 API 真香!
本文首发于公众号【沉浸式趣谈】,探讨 ES2025 新特性 `Promise.try()` 的强大功能。该方法可将同步或异步函数统一包装为 Promise,解决同步错误捕获难题,简化代码逻辑。通过实际案例分析,展示其在 API 调用、混合任务链及文件操作中的应用优势。`Promise.try()` 让 Promise 使用更健壮、一致,是开发者工具箱的有力补充。更多技术分享,请访问我的博客 https://yaolifeng.com 或点赞、评论、转发支持!
72 13
|
4月前
|
前端开发
使用 async/await 结合 try/catch 处理 Promise.reject()抛出的错误时,有什么需要注意的地方?
使用 async/await 结合 try/catch 处理 Promise.reject()抛出的错误时,有什么需要注意的地方?
180 57
|
7月前
|
前端开发 JavaScript 开发者
Async 和 Await 是基于 Promise 实现
【10月更文挑战第30天】Async和Await是基于Promise实现的语法糖,它们通过简洁的语法形式,借助Promise的异步处理机制,为JavaScript开发者提供了一种更优雅、更易于理解和维护的异步编程方式。
92 1
|
7月前
|
前端开发
如何使用async/await解决Promise的缺点?
总的来说,`async/await` 是对 Promise 的一种很好的补充和扩展,它为我们提供了更高效、更易读、更易维护的异步编程方式。通过合理地运用 `async/await`,我们可以更好地解决 Promise 的一些缺点,提升异步代码的质量和开发效率。
169 64
|
7月前
|
前端开发 JavaScript
async/await和Promise在性能上有什么区别?
性能优化是一个综合性的工作,除了考虑异步模式的选择外,还需要关注代码的优化、资源的合理利用等方面。
216 63
|
7月前
|
JSON 前端开发 JavaScript
浅谈JavaScript中的Promise、Async和Await
【10月更文挑战第30天】Promise、Async和Await是JavaScript中强大的异步编程工具,它们各自具有独特的优势和适用场景,开发者可以根据具体的项目需求和代码风格选择合适的方式来处理异步操作,从而编写出更加高效、可读和易于维护的JavaScript代码。
103 1
|
8月前
|
前端开发 JavaScript UED
深入了解JavaScript异步编程:回调、Promise与async/await
【10月更文挑战第11天】深入了解JavaScript异步编程:回调、Promise与async/await
79 0
|
2月前
|
JSON 数据挖掘 API
1688API最新指南:商品详情接口接入与应用
本指南介绍1688商品详情接口的接入与应用,该接口可获取商品标题、价格、规格、库存等详细信息,适用于电商平台开发、数据分析等场景。接口通过商品唯一标识查询,支持HTTP GET/POST请求,返回JSON格式数据,助力开发者高效利用1688海量商品资源。
|
2月前
|
JSON 数据挖掘 API
京东API接口最新指南:店铺所有商品接口的接入与使用
本文介绍京东店铺商品数据接口的应用与功能。通过该接口,商家可自动化获取店铺内所有商品的详细信息,包括基本信息、销售数据及库存状态等,为营销策略制定提供数据支持。此接口采用HTTP请求(GET/POST),需携带店铺ID和授权令牌等参数,返回JSON格式数据,便于解析处理。这对于电商运营、数据分析及竞品研究具有重要价值。