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

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

5.7 all() 实现

Promise对象数组中所有的都为成功返回的Promise对象才成功,有一个失败返回的就为失败。

Promise.all = function (promises) {
  // 返回一个Promise对象
  return new Promise((resolve, reject) => {
    // 记录状态为成功的promise对象个数
    let count = 0;
    // 保存成功promise对象的结果
    let arr = []
    for (let i = 0; i < promises.length; i++) {
      // Promise 对象肯定可以调用 then
      promises[i].then(v => {
        // 状态为成功的个数++
        count++
        // 保证数组中结果集的顺序与传入的promise对象的顺序一样
        arr[i] = v
        // 状态为成功的个数与promise对象数组的个数一样
        if (count === promises.length) {
          resolve(arr)
        }
      }, r => {
        reject(r)
      })
    }
  })
}

测试:

const p1 = Promise.resolve('OK')
      const p2 = Promise.resolve(
        new Promise((resolve, reject) => {
          resolve('OK~~~')
        })
      )
      const p3 = Promise.reject(
        new Promise((resolve, reject) => {
          reject('err')
        })
      )
      const res1 = Promise.all([p1, p2])
      const res2 = Promise.all([p1, p2, p3])
      console.log(res1)
      console.log(res2)

5.8 race()实现

最先改变状态的promise对象的状态为返回的Promise对象的状态,其结果为返回的Promise对象的结果。

Promise.race = function (promises) {
  return new Promise((resolve, reject) => {
    for (let i = 0; i < promises.length; i++) {
      // 第一个改变状态的promise在其回调函数直接改变返回promise的回调函数
      promises[i].then(v => {
        resolve(v)
      }, r => {
        reject(r)
      })
    }
  })
}
const p1 = Promise.resolve(
        new Promise((resolve, reject) => {
          setTimeout(()=>{
            resolve('OK~~~')
          }, 1000)
        })
      )
      const p2 = Promise.resolve('OK')
      const p3 = Promise.reject(
        new Promise((resolve, reject) => {
          reject('err')
        })
      )
      const res1 = Promise.race([p1, p2, p3])
      console.log(res1)

5.9 then方法回调的异步执行

官方的then

const p1 = new Promise((resolve, reject) => {
        resolve('OK')
        console.log(111)
      })
      p1.then((v) => {
        console.log(222)
      })
      console.log(333)

异步任务会在同步任务全部执行完成后才执行

我们的then

修改方法:(原先的回调函数均为同步执行的)将其修改为异步任务

// 状态为成功
    if (this.PromiseState === 'fulfilled' || this.PromiseState === 'resolved') {
      setTimeout(() => {
        callback(onResolved)
      });
    }
    // 状态为失败
    if (this.PromiseState === 'rejected') {
      setTimeout(() => {
        callback(onRejected)
      })
// 定义resolve函数
  function resolve(data) {
    if (self.PromiseState !== 'pending') return // 状态已经修改直接退出
    self.PromiseState = 'fulfilled' // 修改 Promise的状态 PromiseState
    self.PromiseResult = data       // 修改 Promise的结果 PromiseResult
    setTimeout(() => {
      self.callback.forEach(item => { // 调用所有的回调函数
        item.onResolved(self.PromiseResult)
      })
    })
  }
  // 定义reject函数
  function reject(data) {
    if (self.PromiseState !== 'pending') return // 状态已经修改直接退出
    self.PromiseState = 'rejected'  // 修改 Promise的状态 PromiseState
    self.PromiseResult = data       // 修改 Promise的结果 PromiseResult
    setTimeout(() => {
      self.callback.forEach(item => { // 调用所有的回调函数
        item.onRejected(self.PromiseResult)
      })
    })
  }

修改完成后

5.10 封装为Promise类

class Promise {
  constructor(excutor) {
    // 定义 PromiseState PromiseResult 
    this.PromiseState = 'pending' // 默认状态 pending
    this.PromiseResult = null // 结果默认为空
    const self = this // 将 Promise 对象的 this 保存下来
    this.callback = [] // 声明一个数组用于保存回调函数
    // 定义resolve函数
    function resolve(data) {
      if (self.PromiseState !== 'pending') return // 状态已经修改直接退出
      self.PromiseState = 'fulfilled' // 修改 Promise的状态 PromiseState
      self.PromiseResult = data       // 修改 Promise的结果 PromiseResult
      setTimeout(() => {
        self.callback.forEach(item => { // 调用所有的回调函数
          item.onResolved(self.PromiseResult)
        })
      })
    }
    // 定义reject函数
    function reject(data) {
      if (self.PromiseState !== 'pending') return // 状态已经修改直接退出
      self.PromiseState = 'rejected'  // 修改 Promise的状态 PromiseState
      self.PromiseResult = data       // 修改 Promise的结果 PromiseResult
      setTimeout(() => {
        self.callback.forEach(item => { // 调用所有的回调函数
          item.onRejected(self.PromiseResult)
        })
      })
    }
    // 捕获 excutor 中的异常并进行处理
    try {
      // 调用传参传过来的执行器函数  同步调用
      excutor(resolve, reject)
    } catch (e) {
      // 处理异常,改变Promise状态为失败,改变结果
      reject(e)
    }
  }
  then(onResolved, onRejected) {
    const self = this // 保存调用then的Promise对象
    // 判断失败的回调函数
    // 由于报错造成的原因是失败的回调函数为undefined
    // 所以当失败的回调函数为未定义时候,补充一个失败回调
    // 让其报错
    if (typeof onRejected !== 'function') {
      onRejected = reason => {
        throw reason
      }
    }
    // 没有传递成功的回调函数
    // 给一个默认的成功回调函数
    if (typeof onResolved !== 'function') {
      onResolved = value => {
        return value //将resolve中传递的值,即Promise的结果向后传递
      }
    }
    // 执行完then()返回一个Promise对象
    return new Promise((resolve, reject) => {
      // 封装函数
      function callback(type) {
        try {
          const result = type(self.PromiseResult)
          if (result instanceof Promise) { // 如果是Promise的实例对象
            result.then(v => {
              resolve(v) // 调用成功函数,改变返回的Promise对象为成功
            }, r => {
              reject(r) // 调用失败函数,改变返回的Promise对象为失败
            })
          } else {
            resolve(result)
          }
        } catch (e) {
          reject(e)
        }
      }
      // 状态为成功
      if (this.PromiseState === 'fulfilled' || this.PromiseState === 'resolved') {
        setTimeout(() => {
          callback(onResolved)
        });
      }
      // 状态为失败
      if (this.PromiseState === 'rejected') {
        setTimeout(() => {
          callback(onRejected)
        });
      }
      // 状态为 pending
      if (this.PromiseState === 'pending') {
        this.callback.push({
          onResolved: function () {
            callback(onResolved)
          },
          onRejected: function () {
            callback(onRejected)
          }
        })
      }
    })
  }
  catch(onRejected) {
    // catch 方法中执行的是失败的回调函数
    // 与 then 差别为只有失败的回调函数,可以直接使用then
    return this.then(undefined, onRejected)
  }
  // resolve、reject、all、race不属于实例对象,属于类
  // 用static进行修饰
  static resolve(value) {
    return new Promise((resolve, reject) => {
      if (value instanceof Promise) {
        // 为Promise对象,肯定可以调用then
        value.then(v => {
          resolve(v)
        }, r => {
          reject(r)
        })
      } else {
        resolve(value)
      }
    })
  }
  static reject(value) {
    return new Promise((resolve, reject) => {
      reject(value)
    })
  }
  static all(promises) {
    // 返回一个Promise对象
    return new Promise((resolve, reject) => {
      // 记录状态为成功的promise对象个数
      let count = 0;
      // 保存成功promise对象的结果
      let arr = []
      for (let i = 0; i < promises.length; i++) {
        // Promise 对象肯定可以调用 then
        promises[i].then(v => {
          // 状态为成功的个数++
          count++
          // 保证数组中结果集的顺序与传入的promise对象的顺序一样
          arr[i] = v
          // 状态为成功的个数与promise对象数组的个数一样
          if (count === promises.length) {
            resolve(arr)
          }
        }, r => {
          reject(r)
        })
      }
    })
  }
  static race(promises) {
    return new Promise((resolve, reject) => {
      for (let i = 0; i < promises.length; i++) {
        // 第一个改变状态的promise在其回调函数直接改变返回promise的回调函数
        promises[i].then(v => {
          resolve(v)
        }, r => {
          reject(r)
        })
      }
    })
  }
}

测试:

const p1 = new Promise((resolve, reject) => {
        resolve('OK')
        console.log(111)
      })
      p1.then((v) => {
        console.log(222)
      })
      console.log(333)

6 async与await

6.1 mdn 文档

【async】

【await】

6.2 async 函数

  1. async函数的返回值为 promise 对象
async function f1() {
      }
      const res1 = f1()
      console.log(res1)

  1. promise 对象的结果由 async 函数执行的返回值决定(与then的规则一样)
    返回的为非Promise对象的数据,则函数返回的结果为成功的Promise对象,Promise对象的结果为return的结果
async function f1() {
      return 123
    }
    const res1 = f1()
    console.log(res1)

  1. 返回的为失败的Promise,函数返回的为失败的Promise
async function f1() {
      return new Promise((resolve, reject)=>{
        reject('OK')
      })
    }
    const res1 = f1()
    console.log(res1)

  1. 返回的为成功的Promise,函数返回的为成功的Promise
async function f1() {
      return new Promise((resolve, reject)=>{
        resolve('OK')
      })
    }
    const res1 = f1()
    console.log(res1)

  1. 函数抛出错误,返回的为失败的Promise
async function f1() {
      throw 'ERROR'
    }
    const res1 = f1()
    console.log(res1)

6.3 await 表达式

  1. await 右侧的表达式一般为 promise 对象, 但也可以是其它的值,运算相关的也行
  2. 如果表达式是 promise 对象, await 返回的是 promise 成功的值
async function f() {
      const p = Promise.resolve('OK')
      let res = await p
      console.log(res)
    }
    f()

  1. 如果表达式是其它值, 直接将此值作为 await 的返回值
async function f() {
      let res = await 20
      console.log(res)
    }
    f()

  • 注意
    await 必须写在 async 函数中, 但 async 函数中可以没有 await
await 20;

  • 如果 await 的 promise 失败了, 就会抛出异常, 需要通过 try…catch 捕获处理
async function f() {
      const p = Promise.reject('ERROR')
      let res = await p
      console.log(res)
    }
    f()

async function f() {
      const p = Promise.reject('ERROR')
      try {
        let res = await p
      } catch (error) {
        console.log(error)
      }
    }
    f()

6.4 async与await结合实践 – 读取文件

6.4.1 不基于Promise实现 – 回调地狱

const { log } = require('console')
const fs = require('fs')
// 会出现data变量名覆盖
fs.readFile('./content.txt', (err, data1) => {
  if (err) return err
  fs.readFile('./content.txt', (err, data2) => {
    if (err) return err 
    fs.readFile('./content.txt', (err, data3) => {
      if (err) return err
      log( data1+data2+data3 )
    } )
  })
})

6.4.2 基于Promise

const { log } = require('console')
const fs = require('fs')
// util 中的 util.promisify() 可以对读取文件的方法进行封装
const util = require('util')
const myReadFile = util.promisify(fs.readFile)
// 读取文件
async function read() {
  let data1 = await myReadFile('./content.txt')
  let data2 = await myReadFile('./content.txt')
  let data3 = await myReadFile('./content.txt')
  log(data1 + data2 + data3)
}
read()

使用async与await,也便于报错处理,不像fs回调那样每层都要独立的报错处理

const { log } = require('console')
const fs = require('fs')
// util 中的 util.promisify() 可以对读取文件的方法进行封装
const util = require('util')
const myReadFile = util.promisify(fs.readFile)
// 读取文件
async function read() {
  try {
    let data1 = await myReadFile('./content1111111111111.txt')
    let data2 = await myReadFile('./content.txt')
    let data3 = await myReadFile('./content.txt')
    log(data1 + data2 + data3)
  } catch (e) {
    log(e)
  }
}
read()


相关文章
|
1月前
|
前端开发 小程序 API
【微信小程序】-- 使用 npm 包 - API Promise化(四十二)
【微信小程序】-- 使用 npm 包 - API Promise化(四十二)
|
1月前
|
分布式计算 API 数据处理
Flink【基础知识 01】(简介+核心架构+分层API+集群架构+应用场景+特点优势)(一篇即可大概了解flink)
【2月更文挑战第15天】Flink【基础知识 01】(简介+核心架构+分层API+集群架构+应用场景+特点优势)(一篇即可大概了解flink)
60 1
|
3月前
|
JavaScript 前端开发 IDE
Vue3【为什么选择Vue框架、Vue简介 、Vue API 风格 、Vue开发前的准备 、Vue项目目录结构 、模板语法、属性绑定 、 】(一)-全面详解(学习总结---从入门到深化)
Vue3【为什么选择Vue框架、Vue简介 、Vue API 风格 、Vue开发前的准备 、Vue项目目录结构 、模板语法、属性绑定 、 】(一)-全面详解(学习总结---从入门到深化)
52 1
|
8月前
|
前端开发 JavaScript API
Promise API 中的静态方法
捋一捋 Promise 魔法书里的各种静态方法,看看它们有什么用,怎么用,还能给我们带来什么惊喜!🎉
50 1
|
3月前
|
Web App开发 前端开发 测试技术
【Web API系列】使用异步剪贴板API(async clipboard)的图像的编程复制和粘贴
【Web API系列】使用异步剪贴板API(async clipboard)的图像的编程复制和粘贴
80 1
|
5月前
|
小程序 前端开发 API
小程序api封装 promise使用
小程序api封装 promise使用
33 0
|
7月前
|
前端开发 API
Promise 静态 API 的使用方法
Promise 静态 API 的使用方法
38 0
|
8月前
|
前端开发
前端学习笔记202306学习笔记第四十二天-promise的基本使用和状态1
前端学习笔记202306学习笔记第四十二天-promise的基本使用和状态1
36 0
|
1月前
|
前端开发 JavaScript
如何处理 JavaScript 中的异步操作和 Promise?
如何处理 JavaScript 中的异步操作和 Promise?
15 1
|
1月前
|
前端开发 JavaScript
在JavaScript中,什么是promise、怎么使用promise、怎么手写promise
在JavaScript中,什么是promise、怎么使用promise、怎么手写promise
25 4