您好,登錄后才能下訂單哦!
這篇文章主要講解了“javascript之generator生成器函數與asnyc/await語法糖怎么使用”,文中的講解內容簡單清晰,易于學習與理解,下面請大家跟著小編的思路慢慢深入,一起來研究和學習“javascript之generator生成器函數與asnyc/await語法糖怎么使用”吧!
相比于傳統回調函數的方式處理異步調用,Promise最大的優勢就是可以鏈式調用解決回調嵌套的問題。但是這樣寫依然會有大量的回調函數,雖然他們之間沒有嵌套,但是還是沒有達到傳統同步代碼的可讀性。如果以下面的方式寫異步代碼,它是很簡潔,也更容易閱讀的。
// like sync mode try{ const value1 = ajax('/api/url1') console.log(value1) const value2 = ajax('/api/url1') console.log(value2) const value3 = ajax('/api/url1') console.log(value3) const value4 = ajax('/api/url1') console.log(value4) const value5 = ajax('/api/url1') console.log(value5) }catch(err){ console.log(err) }
在ES2015提供了生成器函數(Generator Function)它與普通函數的語法差別在于,在function語句之后和函數名之前,有一個“*”作為生成器函數的標示符。
在我們去調用生成器函數的時候他并不會立即去執行這個函數,而是會得到一個生成器對象,直到我們手動調用對象的next 方法,函數體才會開始執行,我們可以使用關鍵字yield去向外返回一個值,我們可以在next方法的返回值中去拿到這個值。另外再返回的屬性中還有一個done關鍵字來表示生成器是否執行完了,
yield不會像return一樣去結束函數的執行,只是暫停函數的執行,直到外接下一次調用next方法時才會繼續從yield位置往下執行
function * foo () { console.log('start') yield 'foo' } const generator = foo() const result = generator.next()
調用next方法的時候傳入了參數的話,所傳入的參數會作為yield關鍵字的返回值
function * foo () { console.log('start') // 我可以在這里接收next傳入的參數 const res = yield 'foo' console.log(res) // 這是我傳入的參數 } const generator = foo() const result = generator.next('這是我傳入的參數') console.log(result) // { value: 'foo', done: false }
如果我們調用了生成器函數的throw方法,這個方法會給生成器函數內部拋出一個異常
function * foo () { console.log('start') // 我可以在這里接收next傳入的參數 try { const res = yield 'foo' console.log(res) // 這是我傳入的參數 } catch (err) { console.log(err.message) // 拋出錯誤 } } const generator = foo() const result = generator.next('這是我傳入的參數') console.log(result) generator.throw(new Error('拋出錯誤'))
利用生成器函數和Promise來實現異步編程的體驗
function ajax(url) { return new Promise((resove, reject) => { var xhr = new XMLHttpRequest() xhr.open('GET', url) // 新方法可以直接接受一個j對象 xhr.responseType = 'json' xhr.onload = function () { if (this.status === 200) { resove(this.response) } else { reject(new Error(this.statusText)) } } xhr.send() }) } function* main() { const user1 = yield ajax('/json1.json') console.log(user1) const user2 = yield ajax('/json2.json') console.log(user2) const user3 = yield ajax('/json3.json') console.log(user3) } const g = main() const result = g.next() result.value.then(data => { const result2 = g.next(data) if (result2.done) return result2.value.then(data2 => { const result3 = g.next(data2) if (result3.done) return result3.value.then(data3 => { g.next(data3) }) }) })
很明顯生成器的執行器可以使用遞歸的方式去調用
const g = main() function handleResult(result) { if (result.done) return result.value.then(data => { handleResult(g.next(data)) }, err => { g.throw(err) }) } handleResult(g.next())
生成器函數的調用其實都是差不多的,所以我們可以寫一個比較通用的執行器
function co(generator) { const g = generator() function handleResult(result) { if (result.done) return result.value.then(data => { handleResult(g.next(data)) }, err => { g.throw(err) }) } handleResult(g.next()) } co(main)
當然這樣的執行器在社區中已經有一個比較完善的庫了co。這種co的方案在2015年之前是特別流行的,后來在出了async/await語法糖之后,這種方案相對來講就沒有那么普及了。使用generator這種方法最明顯的變化就是異步調用回歸到扁平化了
有了generator之后js異步編程基本上與同步代碼有類似的體驗了,但是使用generator這種異步方案還需要自己手動去寫一個執行器函數,會比較麻煩。在ES2017的版本中新增了一個叫做async的函數,它同樣提供了這種扁平化的編程體驗,并且是語言層面的標準的異步編程語法。其實async函數就是生成器函數更方便的語法糖,所以語法上給generator函數是類似的。
async function main() { try { const user1 = await ajax('/json1.json') console.log(user1) const user2 = await ajax('/json2.json') console.log(user2) const user3 = await ajax('/json3.json') console.log(user3) } catch (error) { console.log(error) } } main()
async 函數返回一個Promise對象,更利于對整體代碼控制
promise.then(() => { console.log('all completed') }).catch(err => { console.log(err) })
感謝各位的閱讀,以上就是“javascript之generator生成器函數與asnyc/await語法糖怎么使用”的內容了,經過本文的學習后,相信大家對javascript之generator生成器函數與asnyc/await語法糖怎么使用這一問題有了更深刻的體會,具體使用情況還需要大家實踐驗證。這里是億速云,小編將為大家推送更多相關知識點的文章,歡迎關注!
免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。