免费爱碰视频在线观看,九九精品国产屋,欧美亚洲尤物久久精品,1024在线观看视频亚洲

      Javascript ES6中 Generator的?async/await Promise 了解一下?

      介紹

      Generator 函數(shù)是 ES6 提供的一種異步編程解決方案,語法行為與傳統(tǒng)函數(shù)完全不同

      生成器對象是由一個 generator function 返回的,并且它符合可迭代協(xié)議和迭代器協(xié)議。

      generator和函數(shù)不同的是,generator由function*定義(注意多出的*號),并且,除了return語句,還可以用yield返回多次。

      回顧下上文提到的解決異步的手段:

      • 回調(diào)函數(shù)
      • promise

      那么,上文我們提到promsie已經(jīng)是一種比較流行的解決異步方案,那么為什么還出現(xiàn)Generator?甚至async/await呢?

      該問題我們留在后面再進(jìn)行分析,下面先認(rèn)識下Generator

      Generator函數(shù)

      執(zhí)行 Generator 函數(shù)會返回一個遍歷器對象,可以依次遍歷 Generator 函數(shù)內(nèi)部的每一個狀態(tài)

      形式上,Generator函數(shù)是一個普通函數(shù),但是有兩個特征:

      • function關(guān)鍵字與函數(shù)名之間有一個星號
      • 函數(shù)體內(nèi)部使用yield表達(dá)式,定義不同的內(nèi)部狀態(tài)

      function* helloWorldGenerator() { yield ‘hello’; yield ‘world’; return ‘ending’;}

      函數(shù)只能返回一次,但是,如果換成generator,就可以一次返回一個數(shù),不斷返回多次。

      什么是生成器?

      生成器是在函數(shù)內(nèi)部運行的一些代碼

      • 返回值后,它會自行暫停,并且——
      • 調(diào)用程序可以要求取消暫停并返回另一個值

      這種“返回”不是傳統(tǒng)的從函數(shù) return。所以它被賦予了一個特殊的名稱——yield。

      生成器語法因語言而異。Javascript 的生成器語法類似于 PHP,但是區(qū)別也很大,如果你希望它們的作用相同,那么最終你會感到非常困惑。

      在 javascript 中,如果想要使用生成器,則需要:

      • 定義特殊的生成器函數(shù)
      • 調(diào)用該函數(shù)創(chuàng)建一個生成器對象
      • 在循環(huán)中使用該生成器對象,或直接調(diào)用其 next 方法

      方法

      Generator.prototype.next()返回一個由 yield表達(dá)式生成的值。

      Generator.prototype.return()返回給定的值并結(jié)束生成器。

      Generator.prototype.throw()向生成器拋出一個錯誤。

      使用

      Generator 函數(shù)會返回一個遍歷器對象,即具有Symbol.iterator屬性,并且返回給自己

      function* gen(){ // some code}var g = gen();g[Symbol.iterator]() === g// true

      通過yield關(guān)鍵字可以暫停generator函數(shù)返回的遍歷器對象的狀態(tài)

      function* helloWorldGenerator() { yield ‘hello’; yield ‘world’; return ‘ending’;}var hw = helloWorldGenerator();

      上述存在三個狀態(tài):hello、world、return

      通過next方法才會遍歷到下一個內(nèi)部狀態(tài),其運行邏輯如下:

      • 遇到y(tǒng)ield表達(dá)式,就暫停執(zhí)行后面的操作,并將緊跟在yield后面的那個表達(dá)式的值,作為返回的對象的value屬性值。
      • 下一次調(diào)用next方法時,再繼續(xù)往下執(zhí)行,直到遇到下一個yield表達(dá)式
      • 如果沒有再遇到新的yield表達(dá)式,就一直運行到函數(shù)結(jié)束,直到return語句為止,并將return語句后面的表達(dá)式的值,作為返回的對象的value屬性值。
      • 如果該函數(shù)沒有return語句,則返回的對象的value屬性值為undefined

      hw.next()// { value: ‘hello’, done: false }hw.next()// { value: ‘world’, done: false }hw.next()// { value: ‘ending’, done: true }hw.next()// { value: undefined, done: true }

      done用來判斷是否存在下個狀態(tài),value對應(yīng)狀態(tài)值

      yield表達(dá)式本身沒有返回值,或者說總是返回undefined

      通過調(diào)用next方法可以帶一個參數(shù),該參數(shù)就會被當(dāng)作上一個yield表達(dá)式的返回值

      function* foo(x) { var y = 2 * (yield (x + 1)); var z = yield (y / 3); return (x + y + z);}var a = foo(5);a.next() // Object{value:6, done:false}a.next() // Object{value:NaN, done:false}a.next() // Object{value:NaN, done:true}var b = foo(5);b.next() // { value:6, done:false }b.next(12) // { value:8, done:false }b.next(13) // { value:42, done:true }

      正因為Generator函數(shù)返回Iterator對象,因此我們還可以通過for…of進(jìn)行遍歷

      function* foo() { yield 1; yield 2; yield 3; yield 4; yield 5; return 6;}for (let v of foo()) { console.log(v);}// 1 2 3 4 5

      原生對象沒有遍歷接口,通過Generator函數(shù)為它加上這個接口,就能使用for…of進(jìn)行遍歷了

      function* objectEntries(obj) { let propKeys = Reflect.ownKeys(obj); for (let propKey of propKeys) { yield [propKey, obj[propKey]]; }}let jane = { first: ‘Jane’, last: ‘Doe’ };for (let [key, value] of objectEntries(jane)) { console.log(`${key}: ${value}`);}// first: Jane// last: Doe

      異步解決方案

      回顧之前展開異步解決的方案:

      • 回調(diào)函數(shù)
      • Promise 對象
      • generator 函數(shù)
      • async/await

      這里通過文件讀取案例,將幾種解決異步的方案進(jìn)行一個比較:

      回調(diào)函數(shù)

      所謂回調(diào)函數(shù),就是把任務(wù)的第二段單獨寫在一個函數(shù)里面,等到重新執(zhí)行這個任務(wù)的時候,再調(diào)用這個函數(shù)

      fs.readFile(‘/etc/fstab’, function (err, data) { if (err) throw err; console.log(data); fs.readFile(‘/etc/shells’, function (err, data) { if (err) throw err; console.log(data); });});

      readFile函數(shù)的第三個參數(shù),就是回調(diào)函數(shù),等到操作系統(tǒng)返回了/etc/passwd這個文件以后,回調(diào)函數(shù)才會執(zhí)行

      傳統(tǒng)的生成器對象

      Firefox (SpiderMonkey) 在 JavaScript 1.7 中也實現(xiàn)了一個較早版本的生成器,其中函數(shù)聲明中的星號(*)不是必需的 (只需在函數(shù)體中使用yield 關(guān)鍵字)。但是,舊式生成器已棄用。不要使用它們;他們將被刪除 (bug 1083482)。

      傳統(tǒng)的生成器方法

      Generator.prototype.next() Non-Standard返回 yield 表達(dá)式產(chǎn)生的值。與 ES2015 生成器對象的 next() 方法對應(yīng)。

      Generator.prototype.close() Non-Standard關(guān)閉生成器,因此執(zhí)行該函數(shù)后調(diào)用next() 函數(shù)時將會拋出 StopIteration 錯誤。與 ES2015 生成器對象的 return() 方法對應(yīng)..

      Generator.prototype.send() Non-Standard用于將值發(fā)送到生成器。 該值由 yield 表達(dá)式返回,并且返回下一個 yield 表達(dá)式產(chǎn)生的值。send(x) 對應(yīng)于 ES2015 生成器對象中的 next(x)

      Generator.prototype.throw() Non-Standard向生成器拋出錯誤。與 ES2015 生成器對象的 throw() 方法對應(yīng)。

      generator函數(shù)中的this問題

      // 正常函數(shù)function F () { this.a = 1}const f = new F()// 調(diào)用構(gòu)造函數(shù)F,返回實例對象f// 將構(gòu)造函數(shù)內(nèi)部中的this指向這個實例對象// 將構(gòu)造函數(shù)中的原型對象賦值給實例對象的原型// 執(zhí)行構(gòu)造函數(shù)中的代碼// 調(diào)用Generator函數(shù)會返回遍歷器對象,而不是實例對象,因此無法獲取到this指向的實例對象上的私有屬性和方法。但是這個遍歷器對象可以繼承Generator函數(shù)的prototype原型對象上的屬性和方法(公有屬性和方法)。function* g() {}g.prototype.hello = function () { return ‘hi!’;};let obj = g();obj instanceof g // trueobj.hello() // ‘hi!’

      上面代碼表明,Generator 函數(shù)g返回的遍歷器obj,是g的實例,而且繼承了g.prototype。但是,如果把g當(dāng)作普通的構(gòu)造函數(shù),并不會生效,因為g返回的總是遍歷器對象,而不是this對象。

      應(yīng)用generator 數(shù)組扁平化

      function* flatten3(arr) { let length = arr.length; for (let i=0; i<length; i++) { let item = arr[i]; if (Array.isArray(item)) { yield* flatten3(item); } else { yield item; } }} let res = [];for (let f of flatten3 (arr)) { res.push(f);}console.log(res)

      迭代方法

      function flatten2(arr) { const stack = […arr]; const res = []; while (stack.length) { // 從棧里取出 const next = stack.pop(); if (Array.isArray(next)) { // 把next扁平化,然后放入stack中 stack.push(…next); } else { res.push(next); } } // reverse to restore input order return res.reverse();}console.log(flatten2(arr))

      Promise

      Promise就是為了解決回調(diào)地獄而產(chǎn)生的,將回調(diào)函數(shù)的嵌套,改成鏈?zhǔn)秸{(diào)用

      const fs = require(‘fs’);const readFile = function (fileName) { return new Promise(function (resolve, reject) { fs.readFile(fileName, function(error, data) { if (error) return reject(error); resolve(data); }); });};readFile(‘/etc/fstab’).then(data =>{ console.log(data) return readFile(‘/etc/shells’)}).then(data => { console.log(data)})

      這種鏈?zhǔn)讲僮餍问?,使異步任?wù)的兩段執(zhí)行更清楚了,但是也存在了很明顯的問題,代碼變得冗雜了,語義化并不強

      generator

      yield表達(dá)式可以暫停函數(shù)執(zhí)行,next方法用于恢復(fù)函數(shù)執(zhí)行,這使得Generator函數(shù)非常適合將異步任務(wù)同步化

      const gen = function* () { const f1 = yield readFile(‘/etc/fstab’); const f2 = yield readFile(‘/etc/shells’); console.log(f1.toString()); console.log(f2.toString());};

      async/await

      將上面Generator函數(shù)改成async/await形式,更為簡潔,語義化更強了

      const asyncReadFile = async function () { const f1 = await readFile(‘/etc/fstab’); const f2 = await readFile(‘/etc/shells’); console.log(f1.toString()); console.log(f2.toString());};

      區(qū)別:

      通過上述代碼進(jìn)行分析,將promise、Generator、async/await進(jìn)行比較:

      • promise和async/await是專門用于處理異步操作的
      • Generator并不是為異步而設(shè)計出來的,它還有其他功能(對象迭代、控制輸出、部署Interator接口…)
      • promise編寫代碼相比Generator、async更為復(fù)雜化,且可讀性也稍差
      • Generator、async需要與promise對象搭配處理異步情況
      • async實質(zhì)是Generator的語法糖,相當(dāng)于會自動執(zhí)行Generator函數(shù)
      • async使用上更為簡潔,將異步代碼以同步的形式進(jìn)行編寫,是處理異步編程的最終方案

      使用場景

      Generator是異步解決的一種方案,最大特點則是將異步操作同步化表達(dá)出來

      function* loadUI() { showLoadingScreen(); yield loadUIDataAsynchronously(); hideLoadingScreen();}var loader = loadUI();// 加載UIloader.next()// 卸載UIloader.next()

      包括redux-saga中間件也充分利用了Generator特性

      import { call, put, takeEvery, takeLatest } from ‘redux-saga/effects’import Api from ‘…’function* fetchUser(action) { try { const user = yield call(Api.fetchUser, action.payload.userId); yield put({type: “USER_FETCH_SUCCEEDED”, user: user}); } catch (e) { yield put({type: “USER_FETCH_FAILED”, message: e.message}); }}function* mySaga() { yield takeEvery(“USER_FETCH_REQUESTED”, fetchUser);}function* mySaga() { yield takeLatest(“USER_FETCH_REQUESTED”, fetchUser);}export default mySaga;

      還能利用Generator函數(shù),在對象上實現(xiàn)Iterator接口

      function* iterEntries(obj) { let keys = Object.keys(obj); for (let i=0; i < keys.length; i++) { let key = keys[i]; yield [key, obj[key]]; }}let myObj = { foo: 3, bar: 7 };for (let [key, value] of iterEntries(myObj)) { console.log(key, value);}// foo 3// bar 7

      給大家分享我收集整理的各種學(xué)習(xí)資料,前端小白交流、學(xué)習(xí)交流,也可以直接問我,我會組織大家一起做項目練習(xí),幫助大家匹配一位學(xué)習(xí)伙伴互相監(jiān)督學(xué)習(xí)-下面是學(xué)習(xí)資料參考。

      前端學(xué)習(xí)交流、自學(xué)、學(xué)習(xí)資料等推薦 – 知乎

      鄭重聲明:本文內(nèi)容及圖片均整理自互聯(lián)網(wǎng),不代表本站立場,版權(quán)歸原作者所有,如有侵權(quán)請聯(lián)系管理員(admin#wlmqw.com)刪除。
      (0)
      用戶投稿
      上一篇 2022年6月27日 15:06
      下一篇 2022年6月27日 15:06

      相關(guān)推薦

      • 75歲之后,還能輕松做好這些事情,多半都會長壽

        前言: 人過75歲已經(jīng)進(jìn)入老年狀態(tài),在這個時候很多人身體狀態(tài)都不是太好,有些人走路的話都成問題。不過在我們的生活當(dāng)中,有很多人在這個時候狀態(tài)還是不錯的,還能做很多事情,而且在任何方…

        2022年5月6日
      • 大衣哥兒子再愛定婚,新兒媳條件優(yōu)越,卻被質(zhì)疑另有所圖

        只不過是為錢而去,老子掙錢兒子花,當(dāng)今社會大衣哥沒有出名誰家姑娘肯嫁給你兒子呢?實話實說。 我問你小朱你有什么學(xué)歷?靠實力說話,別靠老子靠自己努力。朱小偉并不是出眾,有點呆。我看婚…

        2022年5月13日
      • 梅西2進(jìn)球1助攻!賽季首秀踢出勺子倒鉤!他仍能是世界第一人

        原創(chuàng) 8月7日,法甲揭幕戰(zhàn)。雖然姆巴佩因傷缺席,可是梅西和內(nèi)馬爾的上場,還是讓關(guān)注度本來在五大聯(lián)賽中墊底的法甲成為熱門話題。梅西和內(nèi)馬爾在上賽季的表現(xiàn)都低于個人平均水平,梅西是因為…

        2022年8月8日
      • 如何預(yù)防眼尾紋,四個方法教會你

        所謂人老先衰,臉老先老眼。眼的部位如果出現(xiàn)細(xì)紋(比如:眼尾紋),就會讓你看起來更老十幾歲,相反,如果控制好細(xì)紋的產(chǎn)生,同樣能讓你比同齡人年輕十幾歲。[撒花] 這幾個能夠預(yù)防法令紋的…

        2022年8月25日
      • 原來,這才是成年人最好的生活狀態(tài)

        很喜歡木心說過的一句話: “生活的最好狀態(tài),是冷冷清清的風(fēng)風(fēng)火火?!?一面冷冷清清、不慌不忙;另一面呢,卻腳踏實地地用努力改變當(dāng)下,風(fēng)風(fēng)火火地活成自己想要的模樣! 原來,這就是成年…

        2022年7月29日
      • 白蘿卜絲用做餃子餡時,是直接焯一下還是用鹽漬出水分,哪種方式較好?

        白蘿卜絲用做餃子餡時,是直接焯一下還是用鹽漬出水分,哪種方式較好? 相信付出愛是讓自己幸福的最好方式,深深地相信,美食是撫慰人心的不二法門,更多美食問答,請關(guān)注覓源良食,讓我們給您…

        2022年9月19日
      • matplotlib 厘米和英寸的實現(xiàn)方法

        長度計量單位中的厘米和英寸是Python數(shù)據(jù)可視化中的常用計量單位,而且厘米和英寸可以相互換算。這樣,在同一繪圖區(qū)域中,同時使用厘米和英寸作為計量單位就成為可能。在代碼實現(xiàn)上,厘米…

        2022年6月14日
      • 楊紫活動造型 一字肩花瓣上衣清新甜美

        楊紫最近也是在線下辛勤營業(yè)中,最近她的一組活動造型圖釋出,從圖中看起來,紫妹的狀態(tài)不錯,穿白色花瓣裙大秀一字肩,半丸子頭搭配蝴蝶結(jié)發(fā)飾,看起來清新甜美。

        2022年6月8日
      • 中國男籃15分大勝,周琦復(fù)出,全隊6人得分上雙,下場對陣印尼隊

        亞洲杯小組賽第三場,中國隊以95-80大勝中國臺北隊,分差達(dá)到15分,本場比賽,中國隊派出王哲林、顧全、趙睿、胡明軒、孫銘徽首發(fā),周琦迎來復(fù)出,第一節(jié),中國隊氣勢如虹,打出一波進(jìn)攻…

        2022年7月18日
      • 10條護(hù)膚“潛規(guī)則”,做到了,能幫你省下一半買護(hù)膚品的錢

        好的皮膚或許是天生帶來的,但是也和日常生活習(xí)慣息息相關(guān),我觀察過身邊皮膚狀態(tài)好的人,她們大多都不會過度關(guān)注皮膚如何,也并不不會花太多錢在護(hù)膚品上,而是根據(jù)自己的皮膚狀態(tài)合理護(hù)膚。護(hù)…

        2022年5月16日

      聯(lián)系我們

      聯(lián)系郵箱:admin#wlmqw.com
      工作時間:周一至周五,10:30-18:30,節(jié)假日休息