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月前
|
前端开发 小程序 API
【微信小程序】-- 使用 npm 包 - API Promise化(四十二)
【微信小程序】-- 使用 npm 包 - API Promise化(四十二)
|
2月前
|
SQL Java 程序员
Java 8中的Stream API:简介与实用案例
【5月更文挑战第23天】本文将深入探讨Java 8中的Stream API,这是一种能够极大提升Java程序员生产力的新特性。我们将从基础概念开始,然后通过一些实用的案例来展示如何使用Stream API进行数据处理和操作。无论你是Java的初学者还是经验丰富的开发者,本文都将为你提供有价值的信息。
|
2月前
|
安全 Java API
Java 8中的Stream API:简介与实用指南深入理解Java并发编程:线程安全与锁优化
【5月更文挑战第29天】本文旨在介绍Java 8中引入的Stream API,这是一种用于处理集合的新方法。我们将探讨Stream API的基本概念,以及如何使用它来简化集合操作,提高代码的可读性和效率。 【5月更文挑战第29天】 在Java并发编程中,线程安全和性能优化是两个核心议题。本文将深入探讨如何通过不同的锁机制和同步策略来保证多线程环境下的数据一致性,同时避免常见的并发问题如死锁和竞态条件。文章还将介绍现代Java虚拟机(JVM)针对锁的优化技术,包括锁粗化、锁消除以及轻量级锁等概念,并指导开发者如何合理选择和使用这些技术以提升应用的性能。
|
2月前
|
Java API 数据处理
Java 8中的Stream API简介及其在数据处理中的应用
【5月更文挑战第30天】 本文旨在介绍Java 8中引入的Stream API,它是一种用于处理集合的新方法。与传统的循环和迭代器相比,Stream API提供了一种更简洁、高效的方式来处理数据。文章将详细介绍Stream API的基本概念、常用操作以及在实际项目中的应用场景。
|
2月前
|
SQL Java API
Java一分钟之-JPA:Java持久化API简介
【5月更文挑战第14天】Java Persistence API (JPA) 是Java的ORM规范,用于简化数据库操作。常见问题包括实体映射、事务管理和性能问题。避免错误的关键在于明确主键策略、妥善使用事务、优化查询及理解实体生命周期。示例展示了如何定义实体和使用`EntityManager`保存数据。JPA通过标准化API让开发者更专注于业务逻辑,提升开发效率和代码维护性。
31 0
|
2月前
|
分布式计算 API 数据处理
Flink【基础知识 01】(简介+核心架构+分层API+集群架构+应用场景+特点优势)(一篇即可大概了解flink)
【2月更文挑战第15天】Flink【基础知识 01】(简介+核心架构+分层API+集群架构+应用场景+特点优势)(一篇即可大概了解flink)
90 1
|
API 计算机视觉
MLDL之API:关于各国内外大平台API简介、使用方法之详细攻略
MLDL之API:关于各国内外大平台API简介、使用方法之详细攻略
|
1天前
|
JSON 安全 API
如何高效编写API接口:以Python与Flask为例
构建RESTful API的简明教程:使用Python的Flask框架,从环境准备(安装Python,设置虚拟环境,安装Flask)到编写首个API(包括获取用户列表和单个用户信息的路由)。运行API服务器并测试在`http://127.0.0.1:5000/users`。进阶话题包括安全、数据库集成、API文档生成和性能优化。【6月更文挑战第27天】
17 7
|
1天前
|
JSON 安全 API
实战指南:使用PHP构建高性能API接口服务端
构建RESTful API的简要指南:使用PHP和Laravel,先安装Laravel并配置数据库,接着在`api.php`中定义资源路由,创建`PostController`处理CRUD操作,定义`Post`模型与数据库交互。使用Postman测试API功能,如创建文章。别忘了关注安全性、错误处理和性能优化。
12 2
|
3天前
|
人工智能 运维 Serverless
函数计算产品使用问题之启动的实例是否有调用api接口停止功能
函数计算产品作为一种事件驱动的全托管计算服务,让用户能够专注于业务逻辑的编写,而无需关心底层服务器的管理与运维。你可以有效地利用函数计算产品来支撑各类应用场景,从简单的数据处理到复杂的业务逻辑,实现快速、高效、低成本的云上部署与运维。以下是一些关于使用函数计算产品的合集和要点,帮助你更好地理解和应用这一服务。