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


相关文章
|
3月前
|
前端开发 JavaScript 开发者
前端开发中的异步编程:Promise 和 Async/Await 的比较与应用
在现代前端开发中,异步编程是不可或缺的技术。本文将深入探讨Promise和Async/Await这两种主流的异步编程方式,分析它们的优劣势及在实际项目中的应用场景。通过比较它们的语法、可读性和错误处理机制,帮助开发者更好地选择和理解如何在项目中高效地利用这些技术。
|
20天前
|
前端开发 JavaScript 开发者
探索前端开发中的异步编程:Promise与Async/Await
在现代前端开发中,处理异步操作是至关重要的。本文将深入探讨异步编程的核心概念,重点比较JavaScript中的Promise与Async/Await两种异步编程方式。通过实例和比较,读者将能够理解这两种方法的优缺点,如何在实际开发中选择适合的异步编程模式,从而编写更简洁、可维护的代码。
|
2月前
|
前端开发 JavaScript
Vue 中 Promise 的then方法异步使用及async/await 异步使用总结
Vue 中 Promise 的then方法异步使用及async/await 异步使用总结
47 1
|
2月前
|
前端开发 JavaScript
JavaScript异步编程:Promise与async/await的深入探索
【7月更文挑战第9天】Promise和async/await是JavaScript中处理异步编程的两大利器。Promise为异步操作提供了统一的接口和链式调用的能力,而async/await则在此基础上进一步简化了异步代码的书写和阅读。掌握它们,将使我们能够更加高效地编写出清晰、健壮的异步JavaScript代码。
|
2月前
|
前端开发 JavaScript
js 等待接口访问成功后执行指定代码【3种方法】(含async await Promise的使用)
js 等待接口访问成功后执行指定代码【3种方法】(含async await Promise的使用)
30 1
|
2月前
|
前端开发 JavaScript 定位技术
JavaScript 等待异步请求数据返回值后,继续执行代码 —— async await Promise的使用方法
JavaScript 等待异步请求数据返回值后,继续执行代码 —— async await Promise的使用方法
33 1
|
3月前
|
前端开发 JavaScript
JavaScript异步处理避免了单线程阻塞,如回调函数、Promise和async/await。
【6月更文挑战第22天】JavaScript异步处理避免了单线程阻塞,如回调函数、Promise和async/await。回调是基础,用于在操作完成后执行函数;Promise管理异步状态,支持链式调用;async/await提供同步代码外观,简化错误处理。每种技术在处理耗时任务时都起着关键作用。
26 3
|
2月前
|
前端开发 小程序 API
【微信小程序】使用 Promise、async 和 await 将异步API 改写为同步
【微信小程序】使用 Promise、async 和 await 将异步API 改写为同步
32 0
|
2月前
|
JavaScript API
前后端数据交互.js文件的axios的写法,想要往后端发送数据,页面注入API,await的意思是同步等待服务器数据,并返回,axios注入在其他页面,其他页面调用的时候,同步作用
前后端数据交互.js文件的axios的写法,想要往后端发送数据,页面注入API,await的意思是同步等待服务器数据,并返回,axios注入在其他页面,其他页面调用的时候,同步作用
|
API 计算机视觉
MLDL之API:关于各国内外大平台API简介、使用方法之详细攻略
MLDL之API:关于各国内外大平台API简介、使用方法之详细攻略