搞快点

【es6】Promise

  • Promise 是异步编程的一种解决方案,它允许你以一种同步的方式编写异步代码
  • promise:承诺、保证
  • ES6 – Promise
  • JS 是通过回调函数来实现异步编程的,当异步操作多了以后,就会产生回调嵌套回调的问题,这就是回调地狱
  • Promise 方式:将异步操作以同步操作的方式表达出来,避免了层层嵌套的回调函数
  • Promise 新建后立即执行

封装一个 Promise

// 按序读取文件:a -> b -> c
// 按顺序读取 a b c 文件
// 以前
// 读取 a 文件
fs.readFile('./a', (err, data) => {
  if (err) return console.log('读取错误')
  console.log(data.toString())

  // 读取 b 文件
  fs.readFile('./b', (err, data) => {
    if (err) return console.log('读取错误')
    console.log(data.toString())

    // 读取 c 文件
    fs.readFile('./a', (err, data) => {
      if (err) return console.log('读取错误')
      console.log(data.toString())
    })
  })
})

// 使用 Promise
// 封装
// Promise 是一个构造函数
// 通过 new 创建 Promise 的实例对象
function readFile(path) {
  // 实例化 Promise
  const p = new Promise((resolve, reject) => {
    // resolve 表示成功,异步操作成功调用
    // reject  表示失败,异步操作失败调用
    fs.readFile(path, (err, data) => {
      // 读取错误,调用 reject()
      if (err) return reject(err)

      // 读取成功 调用 resolve
      resolve(data.toString())
    })
  })

  // 返回 Promise 对象
  return p
}
// 使用
readFile('a')
  .then((res) => {
    console.log(res)
    return readFile('a')
  })
  .then((res) => {
    console.log(res)
    return readFile('b')
  })
  .then((res) => {
    console.log(res)
  })

promise 的三个状态

  • pending : 等待 (等待成功或者失败去调用)

  • fulfilled : 成功调用(resolve)

  • rejected : 失败调用(reject)

then、catch 和 finally

  • 说明:获取异步操作的结果
  • then() :用于获取异步操作成功时的结果 -> resolve
  • catch():用于获取异步操作失败时的结果 -> reject
  • finally():方法用于指定不管 Promise 对象最后状态如何,都会执行的操作,finally方法的回调函数不接受任何参数
  • 说明:then()方法可以有多个,按照先后顺序执行,通过回调函数返回值传递数据给下一个 then
p
  // onfullfilled 执行
  .then((value) => {
    console.log('文件a的内容为:', value)
  })
  // onrejected 执行
  .catch((err) => {
    console.log('文件读取失败:', err)
  })

// ----------- 或者 -----------
// then 中传两个参数
// then方法的第一个参数是resolved状态的回调函数,第二个参数(可选)是rejected状态的回调函数
p.then(
  // onfullfilled 执行
  (value) => { },
  // onrejected 执行
  (err) => { }
)

all 和 race

MDN-Promise.all()
MDN-Promise.race()

let p1 = new Promise((resolve, reject) => {
  setTimeout(() => {
    resolve('成功1')
  },500)
})

let p2 = new Promise((resolve, reject) => {
  setTimeout(() => {
    resolve('成功2')
  },1500)
})

let p3 = new Promise((resolve, reject) => {
  setTimeout(() => {
    reject('失败')
  }, 1000)
})

// 等待 p1,p2 请求完成
Promise.all([p1, p2]).then(res => {
  console.log(res) // ['成功1', '成功2']
})

// 只要有一个请求被 reject,就会进入 catch 回调
Promise.all([p1, p2, p3]).then(res => {
  console.log(res)
}).catch(error => {
  console.log(error) // '失败'
})

// 始终返回最快的那一个异步,不管resolve还是reject
Promise.race([p1, p2]).then((res) => {
  console.log(res) // '成功1'
}, (error) => {
  console.log(error)
})

Promise.race([p1, p3]).then((res) => {
  console.log(res) // '成功1'
}, (error) => {
  console.log(error)
})

Promise.race([p2, p3]).then((result) => {
  console.log(res)
}, (error) => {
  console.log(error) // '失败'
})

async 和 await

  • 异步编程终极方案

  • async / await 用同步编写代码的方式 处理异步操作的一个方案

  • async:修饰 (修饰一个内部有异步操作的函数) 格式 : async + 函数 (里面有异步操作的函数)

  • await : 等待 (等上一个异步操作完成啊 , 修饰 一个结果是 promise 的)异步操作 格式 : await + 异步操作(结果 promise 对象)

  • async 和 await 是成对出现的,await 只能在 async 函数中使用

// 第一步封装
function readFile(path) {
  // 1. 实例化 promise
  const p = new Promise((resolve, reject) => {
    fs.readFile(path, (err, data) => {
      if (err) {
        // 操作错误 调用 =>  reject  => catch
        return reject(err)
      }
      // 操作成功  调用 => resolve => then
      resolve(data.toString())
    })
  })
  // 2. 返回 promise 对象
  return p
}

// 第二步:使用 (async/await)
// async + 函数 (里面有异步操作的函数)
async function fn() {
  // await + 异步操作(结果promise对象)
  // 读取a文件
  try {
    const res1 = await readFile('./data/a1.txt')
    console.log(res1)
  } catch (error) {
    console.log(error)
  }

  // 读取 b 文件
  const res2 = await readFile('./data/b.txt')
  console.log(res2)

  // 读取 c 文件
  const res3 = await readFile('./data/c.txt')
  console.log(res3)
}

fn()
// 延时函数
function sleep(a, b) {
  const p = new Promise((resolve, reject) => {
    setTimeout(() => {
      resolve(b)
    }, a)
  })
  return p
}

async function fn() {
  const res1 = await sleep(1000, 'a')
  console.log(res1)
  const res2 = await sleep(5000, 'b')
  console.log(res2)
  const res3 = await sleep(3000, 'c')
  console.log(res3)
}
// fn()

sleep(1000, 'a')
  .then((res) => {
    console.log(res)
    return sleep(5000, 'b')
  })
  .then((res) => {
    console.log(res)
    return sleep(3000, 'c')
  })
  .then((res) => {
    console.log(res)
  })

const p1 = Promise.all([sleep(1000, 'a'), sleep(5000, 'b')])
p1.then((res) => {
  console.log(res)
})

const p2 = Promise.race([sleep(1000, 'a'), sleep(5000, 'b')])
p2.then((res) => {
  console.log(res)
})

Promise.try()

实际开发中,经常遇到一种情况:不知道或者不想区分,函数f是同步函数还是异步操作,但是想用 Promise 来处理它。因为这样就可以不管f是否包含异步操作,都用then方法指定下一步流程,用catch方法处理f抛出的错误。

Promise.resolve().then(f)

上面的写法有一个缺点,就是如果f是同步函数,那么它会在本轮事件循环的末尾执行。

const f = () => console.log('now')
Promise.resolve().then(f)
console.log('next')
// next
// now

用async函数

(async () => f())()
.then(...)
.catch(...)

Promise.try方法

const f = () => console.log('now')
Promise.try(f)
console.log('next')
// now
// next

new Promise 和 Promise.resolve()

赞(0) 打赏
未经允许不得转载:稻草人 » 【es6】Promise

评论 抢沙发

  • 昵称 (必填)
  • 邮箱 (必填)
  • 网址