异步流程处理

promise

promise 可以说是很常用的异步处理方法

比如我们使用promise封装一个canvas截图的方法

clip (resolve, reject) {
    // 截屏 获取图片url
    return new Promise((resolve, reject) => {
      html2canvas(document.getElementById('view'), {
        canvas: canvas,
        onrendered: (canvas) => {
          let getImg = canvas.toDataURL('image/png')
          resolve(getImg)
        }
      })
    })
  }
复制代码

实现一个简单的promise

function Promise (executor) {
  let self = this
  self.status = 'pending'
  self.success // 成功的原因
  self.failure // 失败的原因

  // 事件池
  self.resolvePool = []
  self.rejectPool = []

  function resolve (data) {
    if (self.status == 'rejected') return
    self.status = 'resolved'
    self.success = data
    // 执行队列
    self.resolvePool.forEach(function (cb){
      cb(self.success)
    })
  }
  function reject (data) {
    if (self.status == 'resolved') return
    self.status = 'rejected'
    self.failure = data
    // 执行队列
    self.rejectPool.forEach(function (cb){
      cb(self.failure)
    })
  }

  // new一个实例就会立即执行这个promise
  executor(resolve, reject)
}

// then
Promise.prototype.then = function (onFulfilled, onRejected)  {
  let self = this
  let promiseStatus = self.status
  if (promiseStatus == 'resolved') {
    onFulfilled(self.success)
  }
  if (promiseStatus == 'rejected') {
    onRejected(self.failure)
  }

  // 很有可能此时状态为 pending
  if (promiseStatus == 'pending') {
    // 放入事件池中等待执行
    self.resolvePool.push(function () {
      onFulfilled(self.success)
    })
    self.rejectPool.push(function () {
      onRejected(self.failure)
    })
  }
}

复制代码

Iterator

let target = beIteraor({name: 'mxx', address: 'beijing'}) 

target.next()
target.next()

复制代码

Iterator 是一个迭代器对象 每次从集合中取出一项 并且跟踪当前序列所在位置

通过使用next方法 返回一个包含value和done两个属性的对象

{value: 当前对象成员, done: Boolean}

复制代码

Iterator 简易实现

let target = beIteraor(['mxx', 'beijing'])

let a = target.next() 
let b = target.next()
let c = target.next()

// { value: 'mxx', done: false } { value: 'beijing', done: false } { value: 'undefined', done: true }

// 返回一个具有next方法的对象
function beIteraor(ary) {
  let index = 0
  let len = ary.length
  return {
    next: function () {
      // 调用next方法  返回 {value, done} 并且指针移动位置
      let done =  ~~index == ~~len
      // 如果指针位置移动到末尾 则返回undefined 否则返回当前位置成员
      let value =  done ? 'undefined' : ary[index]
      index++
      return {value, done}
    }
  }
}

复制代码

generator

  • generator 函数生成一个迭代器
<!-- 函数 注: 这里的read函数直接返回文件中内容 -->
function * getCont () {
  let name = yield 'youchangjing'
  let address = yield 'beijing'
  return name + address
}

<!-- 如何执行 -->

let getC = getCont()
getC.next() // {value: 'youchangjing', done: false}
getC.next() // {value: 'beijing' , done: false}
getC.next() // {value: undefined , done: true}
复制代码

可以看到 generator 函数调用和普通函数一样 fn() 即可 但是函数并不会执行 只有当调用next方法 才能执行到第一个状态

generator 是分段执行的 yield表示暂停执行 next方法恢复函数执行

目前来说 浏览器对 generator 支持情况还是很不错的

co

如果 yield 后面是一个 promise 函数 可以配合co 库来使用


<!-- read函数  -- 封装的一个简易的promise -->
function read(dir) {
  return new Promise((resolve, reject) => {
    fs.readFile(dir, 'utf-8', (err, cont) => {
      if (err) reject(err)
      resolve(cont)
    })
  })
}

<!-- generator -->

function * getCont () {
  let name = yield read('name.js')
  let address = yield read('address.js')
  return name + address
}

<!-- 配合co库 -->

co(getCont()).then(function (cont) {
  console.log(cont) 
})

复制代码

简单的CO实现原理

  • co 的参数是一个迭代器

  • co 返回的是promise 返回的promise 接受 generator 函数的 value

  • co 内部可以使 generator 函数 一直执行到 done 为TRUE

function co(iterator) {
  return new Promise(function (resolve, reject) {
    function next(cont) {
      let {value, done} = iterator.next(cont)
      <!-- value 也是一个promise  -->
      if (done) {
        <!-- 如果 done 为TRUE 则将value 传入 resolve -->
        resolve(value)
      } else {
        <!-- done 为FALSE 则执行其then 方法 用于获取其data传递给 next -->
        value.then(function (data) {
          next(data) 
          <!-- next 递归 -->
        }, reject)
      }
    }
    next()
  })
}
复制代码

async await

async await 可以看做 co + generator 的语法糖

虽然co库可以帮我们自行处理generator 但是又要使用yield 又要封装promise 也是有点麻烦 所以转向 ES7 中的 async await

目前 async await 在Bable, Node 7+ 中被支持

async function getCont() {
  let people = await read('./file.js')
  let who = await read('./who.js')
  return people + who
}

getCont().then((data) => console.log(data))

复制代码
  • async 返回 promise

await

await 顾名思义 等待。那他在等待什么呢。 这个取决于await 后面跟着的内容

await 'mxx'
<!-- 等待非promise -->

await IamPromise()
<!-- 等待 promise -->

复制代码

如果 await 等待的不是一个 promise 那么await表达式的运算结果就是 它等到的东西 (其实await会将其转为一个立即resolve的promise对象)

如果 await 等待的是promise 那么他会阻塞后面的代码 等着Promise 对象 resolve 然后得到其值作为 await表达式的运算结果

function getRank () {
  return 12345
}

async function getType () {
  let name = await read('who.js')
  <!-- read为promise -->
  console.log(name)
  let rank = await getRank()
  <!-- getRank 为普通函数  -->
  console.log(rank)
}

复制代码
  • 如果我们在普通函数中使用await会被阻塞吗

好吧~~ 直接报错了

错误捕获

async 中有两种错误处理方式

1 可以在 async 函数中 使用try catch

async 中对try catch方法做了处理 使其可以捕获异步的错误


async function () {
  try {

  } catch (e) {
    console.log(e)
  }
}

复制代码

2 在then中进行错误捕获

getCont().then().catch((e) => console.log(e))

复制代码

如果async函数中使用了try catch 那么后面的then方法将会进入成功态 【相当于promise返回的是 undefined 】

相关资料

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
在Vue.js 2.x中,有多种方式来处理异步流程。下面我将介绍一些常见的机制和技术。 1. 回调函数:回调函数是一种传统的处理异步操作的方式。你可以在异步操作完成后指定一个回调函数,然后在异步操作中调用该回调函数来处理结果。例如,在发送网络请求时,你可以指定一个回调函数来处理返回的数据。 2. Promise:Promise是一种用于处理异步操作的对象。它可以表示一个异步操作的最终结果(可能是成功的值或失败的原因)。你可以使用`new Promise`来创建一个Promise对象,并使用`.then`方法来处理异步操作成功的情况,使用`.catch`方法来处理异步操作失败的情况。 3. async/await:async/await是JavaScript中处理异步操作的一种语法糖。它基于Promise,并提供了更简洁、更可读的方式来处理异步流程。通过在函数前加上`async`关键字,你可以在函数内部使用`await`关键字来等待一个返回Promise的表达式执行完成。这样可以使异步代码看起来更像同步代码。 4. Vue生命周期钩子函数:Vue提供了一系列的生命周期钩子函数,你可以在这些钩子函数中执行异步操作。比如,在`created`钩子函数中发送网络请求获取数据,或在`mounted`钩子函数中处理DOM更新后的操作。 5. 第三方库:Vue.js生态系统中有许多第三方库可以帮助你处理异步流程,比如axios用于发送网络请求,vuex用于管理应用的状态等。这些库提供了更高级的异步处理功能和工具。 总结起来,Vue.js提供了多种方式来处理异步流程,包括回调函数、Promise、async/await、Vue生命周期钩子函数和第三方库等。你可以根据具体的需求选择适合的方式来处理异步操作。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值