日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當(dāng)前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

异步流程处理

發(fā)布時間:2024/1/17 编程问答 29 豆豆
生活随笔 收集整理的這篇文章主要介紹了 异步流程处理 小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.

promise

promise 可以說是很常用的異步處理方法

比如我們使用promise封裝一個canvas截圖的方法

clip (resolve, reject) {// 截屏 獲取圖片urlreturn new Promise((resolve, reject) => {html2canvas(document.getElementById('view'), {canvas: canvas,onrendered: (canvas) => {let getImg = canvas.toDataURL('image/png')resolve(getImg)}})})} 復(fù)制代碼

實(shí)現(xiàn)一個簡單的promise

function Promise (executor) {let self = thisself.status = 'pending'self.success // 成功的原因self.failure // 失敗的原因// 事件池self.resolvePool = []self.rejectPool = []function resolve (data) {if (self.status == 'rejected') returnself.status = 'resolved'self.success = data// 執(zhí)行隊(duì)列self.resolvePool.forEach(function (cb){cb(self.success)})}function reject (data) {if (self.status == 'resolved') returnself.status = 'rejected'self.failure = data// 執(zhí)行隊(duì)列self.rejectPool.forEach(function (cb){cb(self.failure)})}// new一個實(shí)例就會立即執(zhí)行這個promiseexecutor(resolve, reject) }// then Promise.prototype.then = function (onFulfilled, onRejected) {let self = thislet promiseStatus = self.statusif (promiseStatus == 'resolved') {onFulfilled(self.success)}if (promiseStatus == 'rejected') {onRejected(self.failure)}// 很有可能此時狀態(tài)為 pendingif (promiseStatus == 'pending') {// 放入事件池中等待執(zhí)行self.resolvePool.push(function () {onFulfilled(self.success)})self.rejectPool.push(function () {onRejected(self.failure)})} }復(fù)制代碼

Iterator

let target = beIteraor({name: 'mxx', address: 'beijing'}) target.next() target.next()復(fù)制代碼

Iterator 是一個迭代器對象 每次從集合中取出一項(xiàng) 并且跟蹤當(dāng)前序列所在位置

通過使用next方法 返回一個包含value和done兩個屬性的對象

{value: 當(dāng)前對象成員, done: Boolean}復(fù)制代碼

Iterator 簡易實(shí)現(xiàn)

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 = 0let len = ary.lengthreturn {next: function () {// 調(diào)用next方法 返回 {value, done} 并且指針移動位置let done = ~~index == ~~len// 如果指針位置移動到末尾 則返回undefined 否則返回當(dāng)前位置成員let value = done ? 'undefined' : ary[index]index++return {value, done}}} }復(fù)制代碼

generator

  • generator 函數(shù)生成一個迭代器
<!-- 函數(shù) 注: 這里的read函數(shù)直接返回文件中內(nèi)容 --> function * getCont () {let name = yield 'youchangjing'let address = yield 'beijing'return name + address }<!-- 如何執(zhí)行 -->let getC = getCont() getC.next() // {value: 'youchangjing', done: false} getC.next() // {value: 'beijing' , done: false} getC.next() // {value: undefined , done: true} 復(fù)制代碼

可以看到 generator 函數(shù)調(diào)用和普通函數(shù)一樣 fn() 即可 但是函數(shù)并不會執(zhí)行 只有當(dāng)調(diào)用next方法 才能執(zhí)行到第一個狀態(tài)

generator 是分段執(zhí)行的 yield表示暫停執(zhí)行 next方法恢復(fù)函數(shù)執(zhí)行

目前來說 瀏覽器對 generator 支持情況還是很不錯的

co

如果 yield 后面是一個 promise 函數(shù) 可以配合co 庫來使用

<!-- read函數(shù) -- 封裝的一個簡易的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) })復(fù)制代碼

簡單的CO實(shí)現(xiàn)原理

  • co 的參數(shù)是一個迭代器

  • co 返回的是promise 返回的promise 接受 generator 函數(shù)的 value

  • co 內(nèi)部可以使 generator 函數(shù) 一直執(zhí)行到 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 則執(zhí)行其then 方法 用于獲取其data傳遞給 next -->value.then(function (data) {next(data) <!-- next 遞歸 -->}, reject)}}next()}) } 復(fù)制代碼

async await

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

雖然co庫可以幫我們自行處理generator 但是又要使用yield 又要封裝promise 也是有點(diǎn)麻煩 所以轉(zhuǎn)向 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))復(fù)制代碼
  • async 返回 promise

await

await 顧名思義 等待。那他在等待什么呢。 這個取決于await 后面跟著的內(nèi)容

await 'mxx' <!-- 等待非promise -->await IamPromise() <!-- 等待 promise -->復(fù)制代碼

如果 await 等待的不是一個 promise 那么await表達(dá)式的運(yùn)算結(jié)果就是 它等到的東西 (其實(shí)await會將其轉(zhuǎn)為一個立即resolve的promise對象)

如果 await 等待的是promise 那么他會阻塞后面的代碼 等著Promise 對象 resolve 然后得到其值作為 await表達(dá)式的運(yùn)算結(jié)果

function getRank () {return 12345 }async function getType () {let name = await read('who.js')<!-- read為promise -->console.log(name)let rank = await getRank()<!-- getRank 為普通函數(shù) -->console.log(rank) }復(fù)制代碼
  • 如果我們在普通函數(shù)中使用await會被阻塞嗎

好吧~~ 直接報(bào)錯了

錯誤捕獲

async 中有兩種錯誤處理方式

1 可以在 async 函數(shù)中 使用try catch

async 中對try catch方法做了處理 使其可以捕獲異步的錯誤

async function () {try {} catch (e) {console.log(e)} }復(fù)制代碼

2 在then中進(jìn)行錯誤捕獲

getCont().then().catch((e) => console.log(e))復(fù)制代碼

如果async函數(shù)中使用了try catch 那么后面的then方法將會進(jìn)入成功態(tài) 【相當(dāng)于promise返回的是 undefined 】

相關(guān)資料

  • bluebird

  • promise A+

  • Tterator

  • async

  • await

總結(jié)

以上是生活随笔為你收集整理的异步流程处理的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網(wǎng)站內(nèi)容還不錯,歡迎將生活随笔推薦給好友。