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


相关文章
|
5月前
|
前端开发 JavaScript 开发者
前端开发中的异步编程:Promise 和 Async/Await 的比较与应用
在现代前端开发中,异步编程是不可或缺的技术。本文将深入探讨Promise和Async/Await这两种主流的异步编程方式,分析它们的优劣势及在实际项目中的应用场景。通过比较它们的语法、可读性和错误处理机制,帮助开发者更好地选择和理解如何在项目中高效地利用这些技术。
|
12天前
|
前端开发 JavaScript 开发者
Async 和 Await 是基于 Promise 实现
【10月更文挑战第30天】Async和Await是基于Promise实现的语法糖,它们通过简洁的语法形式,借助Promise的异步处理机制,为JavaScript开发者提供了一种更优雅、更易于理解和维护的异步编程方式。
21 1
|
12天前
|
JSON 前端开发 JavaScript
浅谈JavaScript中的Promise、Async和Await
【10月更文挑战第30天】Promise、Async和Await是JavaScript中强大的异步编程工具,它们各自具有独特的优势和适用场景,开发者可以根据具体的项目需求和代码风格选择合适的方式来处理异步操作,从而编写出更加高效、可读和易于维护的JavaScript代码。
19 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
11 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 异步使用总结
135 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代码。

热门文章

最新文章