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


相关文章
|
5月前
|
前端开发 JavaScript 开发者
前端开发中的异步编程:Promise 和 Async/Await 的比较与应用
在现代前端开发中,异步编程是不可或缺的技术。本文将深入探讨Promise和Async/Await这两种主流的异步编程方式,分析它们的优劣势及在实际项目中的应用场景。通过比较它们的语法、可读性和错误处理机制,帮助开发者更好地选择和理解如何在项目中高效地利用这些技术。
|
18天前
|
前端开发 JavaScript 开发者
Async 和 Await 是基于 Promise 实现
【10月更文挑战第30天】Async和Await是基于Promise实现的语法糖,它们通过简洁的语法形式,借助Promise的异步处理机制,为JavaScript开发者提供了一种更优雅、更易于理解和维护的异步编程方式。
23 1
|
18天前
|
JSON 前端开发 JavaScript
浅谈JavaScript中的Promise、Async和Await
【10月更文挑战第30天】Promise、Async和Await是JavaScript中强大的异步编程工具,它们各自具有独特的优势和适用场景,开发者可以根据具体的项目需求和代码风格选择合适的方式来处理异步操作,从而编写出更加高效、可读和易于维护的JavaScript代码。
22 1
|
1月前
|
前端开发 JavaScript
setTimeout、Promise、Async/Await 的区别
`setTimeout` 是用于延迟执行函数的简单方法;`Promise` 表示异步操作的最终完成或失败;`Async/Await` 是基于 Promise 的语法糖,使异步代码更易读和维护。三者都用于处理异步操作,但使用场景和语法有所不同。
|
1月前
|
前端开发 JavaScript 开发者
JavaScript 中的异步编程:深入了解 Promise 和 async/await
【10月更文挑战第8天】JavaScript 中的异步编程:深入了解 Promise 和 async/await
|
1月前
|
前端开发 JavaScript UED
深入了解JavaScript异步编程:回调、Promise与async/await
【10月更文挑战第11天】深入了解JavaScript异步编程:回调、Promise与async/await
16 0
|
2月前
|
前端开发 JavaScript
解决异步问题,教你如何写出优雅的promise和async/await,告别callback回调地狱!
该文章教授了如何使用Promise和async/await来解决异步编程问题,从而避免回调地狱,使代码更加清晰和易于管理。
解决异步问题,教你如何写出优雅的promise和async/await,告别callback回调地狱!
|
4月前
|
前端开发 JavaScript
Vue 中 Promise 的then方法异步使用及async/await 异步使用总结
Vue 中 Promise 的then方法异步使用及async/await 异步使用总结
145 1
|
3月前
|
前端开发 JavaScript 开发者
探索前端开发中的异步编程:Promise与Async/Await
在现代前端开发中,处理异步操作是至关重要的。本文将深入探讨异步编程的核心概念,重点比较JavaScript中的Promise与Async/Await两种异步编程方式。通过实例和比较,读者将能够理解这两种方法的优缺点,如何在实际开发中选择适合的异步编程模式,从而编写更简洁、可维护的代码。
|
4月前
|
前端开发 JavaScript
JavaScript异步编程:Promise与async/await的深入探索
【7月更文挑战第9天】Promise和async/await是JavaScript中处理异步编程的两大利器。Promise为异步操作提供了统一的接口和链式调用的能力,而async/await则在此基础上进一步简化了异步代码的书写和阅读。掌握它们,将使我们能够更加高效地编写出清晰、健壮的异步JavaScript代码。

热门文章

最新文章

下一篇
无影云桌面