ES6中的迭代器、Generator函數以及Generator函數的非同步操作

来源:https://www.cnblogs.com/ludashi/archive/2019/05/12/10666084.html
-Advertisement-
Play Games

最近在寫RN相關的東西,其中涉及到了redux-saga ,saga的實現原理就是ES6中的Generator函數,而Generator函數又和迭代器有著密不可分的關係。所以本篇博客先學習總結了iterator相關的東西,然後又介紹了Generator相關的內容,最後介紹了使用Generator進行 ...


最近在寫RN相關的東西,其中涉及到了redux-saga ,saga的實現原理就是ES6中的Generator函數,而Generator函數又和迭代器有著密不可分的關係。所以本篇博客先學習總結了iterator相關的東西,然後又介紹了Generator相關的內容,最後介紹了使用Generator進行非同步編程。本篇博客所涉及的示例使用TypeScript語言編寫,當然所涉及的特性是基於ES6規範的,使用TS語言不影響來闡述和總結ES6的相關特性。下篇博客準備系統梳理一下saga相關的內容。

 

一、迭代器

之前再聊迭代器模式時,使用Swift語言自定義過迭代器,在TS中也有迭代器。此處的迭代器與之前所介紹的迭代器是大同小異的。首先我們先來自定義一個迭代器,然後再看一下ES6中的迭代器的使用方式。

1、自定義迭代器

下方定義了一個迭代器函數,函數說明如下:

  • 該函數接收一個數組類型的參數,我們可以將需要創建迭代器的數組作為參數傳進來。
  • 函數內部定義了一個 nextIndex 參數用來記錄迭代器的位置。
  • 該函數返回一個迭代器對象,該迭代器對象包含一個key為 next , value為匿名函數的屬性。
  • 這個key為 next 的匿名方法的返回值為每次迭代器的返回結果對象,這個結果對象由 兩個屬性組成,value表示本次迭代器的值,done表示迭代器遍歷是否結束。
  • 遍歷到最後,最終返回的值為 { value: undefine, done: true }, 也就意味著迭代器遍歷結束,value是undefined, done為true。  

 

自定義完迭代器後,我們就可以對上述代碼進行測試了。

  • 首先創建了一個數組,然後將數組傳給 makeIterator 函數。而 makeIterator 函數會返回一個含有next方法的迭代器對象。
  • 我們將這個迭代器對象命名為 iterator,我們就可以通過 iterator的next方法來依次獲取數組中的值了。
  • 我們通過 while 迴圈來不斷的調用 iterator中的next方法,直到next方法返回的對象中的done值為true時,表示遍歷結束。
  • 遍歷結束後,我們再次調用 next() 方法,得到的是{ value: undefind, done: true } 的對象,表示遍歷結束,獲取的value值為 undefined。

 

2、ES6中的迭代器

類似於Swift語言的特性,ES6規範中我們可以直接通過一些對象獲取該對象所對應的迭代器,如下所示:

  • 下方示例中使用的數組和上面使用的list是一個,首先我們通過 list[Symbol.iterator]() 的方式獲取了 list對應的迭代器。(Symbol也是一種數據類型, 該數據類型用來表示獨一無二的對象)
  • 該迭代器的使用方式和輸出結果與上述我們自定義的迭代器的使用方式完全一致, 輸出結果與之前的結果也是一致的。

 

3、使用 for - of 遍歷迭代器

上述方式創建的迭代器我們是使用的while迴圈來進行遍歷的,除了while迴圈,我們還可以通過for-of 進行遍歷。此處的 for - of遍歷方式類似於Swift語言中的 for - in迴圈,可以依次的自動去除迭代器中的值。下方就是使用for - of 來迴圈遍歷創建的迭代器。

從下方示例中我們不難看出直接輸出的是迭代器返回對象的value值。

 

4、在類中添加迭代器

我們可以在自己的類中添加相關方法,使我們自己的類支持迭代器。下方就創建了一個 RangeIterator 類,該類的作用是可以定義一個範圍,構造器可以接受兩個值,一個是範圍的起始位置另一個是範圍的結束點。下方我們為該範圍類添加了自定義迭代器,具體說明如下:

  • 在該類中添加了一個名為 next 的箭頭函數,在該函數中做的事情與之前我們自定義的next方法差不多,主要是用來獲取下一個值然後返回。
  • 然後又實現一個[Symbole.iterator]函數,用來獲取迭代器對象。
  • 最後我們可看到定義的範圍對象可以向迭代器那樣使用for-of進行遍歷。

 

 

5、調用迭代器的場景

迭代器的使用場景還是蠻多的,解構賦值、擴展運算符、Generator函數、yield*, 下方會簡單的列舉出來。

(1)、對數組或者集合的解構賦值

在下方代碼片段中首先創建了一個名為 mySet 的集合對象。然後通過迴圈給集合中添加了一些值。然後通過 解構賦值 的形式,取出了 mySet 中的第一個值和第二個值。此刻的結構賦值會調用集合的迭代器介面,取出第一個值和第二個值,分別賦值給 first 和 second。

第二個紅框中在結構賦值是使用了擴展運算符,該操作符會使 others 接收 firstItem 剩下的值。

 

(2)、擴展運算符 ...  

接下來來看另一個擴展運算符的例子。

  • 首先定義了一個字元串,然後通過擴展運算符將該字元串的每個字元拆分到一個數組中,輸出結果如下所示。
  • 擴展運算符還可以使用到對象上,如第二個示例所示。

 

(3)、在Generator函數的 yield * 中使用

稍後會詳細的介紹 Generator 函數,一個Generator 函數返回的是一個迭代器,我們可以調用該迭代器的 next 方法來執行每一個 yield。在 Generator 函數中,可以使用 yield * 後邊跟一個可便遍歷的結構,這樣我們就可以在外部統一使用 next 來訪問這個可遍歷的結構的每一個值,如下所示:

 

 

二、Generator函數及非同步編程

理解完迭代器,接下來來看一下Generator函數。如果做過RN開發的話,如果使用過 redux - saga的話,應該對Generator函數不陌生。Generator函數是ES6提供的非同步編程的解決方案,解析了我們先看一下Generator函數基本使用方式,再看一下如何使用Generator函數進行非同步編程。

1、Generator函數的定義和使用

下方定義了一個 Generator函數,Generator函數的定義與普通函數的定義差不多,只不過是function關鍵字後邊跟了一個*號。然後函數體內部使用了一個個 yield語句來表明每一步的操作。定義完Generator函數後,下方緊接著的是使用,首先調用該Generator函數獲取了一個迭代器,每次執行這個迭代器的next方法都會一次的執行一個yield語句。輸出結果和上面的迭代器沒啥區別。

 

2、next的參數

在調用Generator函數返回的迭代器時,是可以往next方法中傳入參數的。next 方法可以帶一個參數,該參數被當做上一個 yield 語句的返回值。下方就是給 next 傳參的一個示例:

  • 下方定義了一個Generator函數,用來輸出自增的值,每次調用next都會獲取一個自增的值。
  • 當調用 rg.next(true) 時,這個true就會被賦值給 reset, 因為這個reset被視為上個yield的返回值,上一個yield執行後,會將index設置為 -1
  • 那麼rg.next(true)對應的 yield執行是,index是從 -1 開始自增的,自增後為0,所以 rg.next(true) 對應的 yield 的值為0。

 

下方是另一個示例:

  • 下方定義了一個名為testNextValue的Generator函數,該函數本身接收了一個參數。
  • 在調用該Generator函數時,傳入了一個參數,這個參數不是Next的參數,是Generator函數本身的參數。Generator函數在調用時,函數體並不會馬上執行,在調用next函數時才會執行函數中yield語句體。
  • 第一次調用Next,給Next傳入了一個值 5,也就是說明 x = 5。第一次執行next會調用第一個 yield 語句體,test1.next(2) = x + 1 = 5 + 1 = 6, 所以第一次調用next的結果值為 6
  • 第二次調用 Next,傳入的Next參數為3。這個3 被作為上一個 yield 語句體的返回值,yield(x + 1) 的返回值為 3。那麼 y 的值就為 2 * 3 = 6。yield中的值為 y / 3 = 2所以第二次執行next獲取的值為 2
  • 第三次調用Next傳入的參數為 4,這個 4 被作為上個yield語句體返回的參數,所以z = 4, 上分析過了 x = 5, y = 6, 所以 x + y + z = 15, 第三次執行next為 15
  • 再次調用Next,因為語句體執行完了,所以獲取到的是undefined。

 

 

三、使用Generator函數進行非同步編程

接下來實現一個簡單的示例,使用Generator函數結合Promise回調模擬一下非同步編程。

首先定義了一個 getPromise函數,該函數接收兩個參數,一個參數表示網路請求的參數,另一個參數表示請求時間。該函數返回一個 Promise對象,在Promise對象中我們使用了setTimeout來模擬請求的延遲,根據傳入的timeout來決定延遲時間,延遲時間到達後會執行 resolve方法,將相關值回調出來。

 

然後定義了一個Generator函數,在該函數中通過yield來調用每個函數,下方的Generator函數比較簡單,在此就不做過多贅述了。 

 

然後我們通過for -of 一次執行Generator函數的next方法,進而來執行每個getPromise方法。

  

下方是具體的執行結果,從執行結果中不難看出,每次獲取的yield值是一個Promise對象,我們可在該Promise對象的then方法中獲取到相關的結果值。從輸出順序中可以看出,會先輸出時間小的那個結果。

 

本篇博客就先到這兒吧,下篇會聊一些saga的相關內容。

 


您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • 比如: DECLARE @t AS TABLE([Datas] NVARCHAR(40)) INSERT INTO @t ([Datas]) VALUES(N'DF'),(N'W4F'),(N'EYY'),(N'ER'),(N'GFF'),(N'A445') SELECT [Datas] FROM ...
  • 1、創建表時數據預設值的設置:(預設值可以為NULL) 2、數據的非空限制: 3、數據的唯一性的設置:(可以插入多個NULL,不是重覆,是都沒有值) 4、主鍵:(非空+唯一) 5、自增長(必須是int類型,而且是主鍵) 6、外鍵約束(減少冗餘):(正常欄位1與欄位5名一樣,如一個為部門表,一個為員工 ...
  • SQL(Structred Query Language)結構化查詢語言:和資料庫交互的語言,進行資料庫管理的語言。 一、資料庫的操作: 1、查詢所有資料庫: show databases; 2、創建資料庫: create database 資料庫名 [default] character set ...
  • 一、序言 1、MySQL簡介 本機安裝的是MySQL5.7資料庫,採用離線安裝的方式,筆者打算把資料庫學懂後再升級為8.0版本的。MySQL其實是一個數據管理系統(DataBase Managment System, DBSM),既包括數據的存儲,又具有有數據的管理功能。MySQL5.7預設的引擎是 ...
  • 今天是母親節,它是在每一年的五月份的第二個星期天,而父親節,是在每一個的六月份的第三個星期天。 把星期天設置為每周的開始,將一周的第一天設置為從 1 到 7 的一個數字。 參考MSDN:https://docs.microsoft.com/zh-cn/sql/t-sql/statements/set ...
  • 文章大綱 一、基礎知識學習二、Redis常見的幾種架構及優缺點總結三、Redis之Redis Sentinel(哨兵)實戰四、Redis之Redis Cluster(分散式集群)實戰五、Java之Jedis連接Redis(Redis Cluster版本)六、Redis之雲平臺介紹七、項目源碼與資料下 ...
  • "官方文檔" 關於 Vector,在官方開髮指南中介紹。本文章是由個人翻譯官方指南然後添加個人理解完成。 由於個人精力有限,多個渠道發佈,排版上可能會有問題,如果影響查看,請移步 Android 開發者家園 Vector Drawables 概述 VectorDrawable 和 AnimatedV ...
  • 修改好的代碼下載地址: https://github.com/Vico H/Launcher 不顯示開機嚮導 =========== 修改Launcher2.java的代碼 (文件位置: /alps/packages/apps/Launcher2/src/com/android/launcher2/ ...
一周排行
    -Advertisement-
    Play Games
  • 移動開發(一):使用.NET MAUI開發第一個安卓APP 對於工作多年的C#程式員來說,近來想嘗試開發一款安卓APP,考慮了很久最終選擇使用.NET MAUI這個微軟官方的框架來嘗試體驗開發安卓APP,畢竟是使用Visual Studio開發工具,使用起來也比較的順手,結合微軟官方的教程進行了安卓 ...
  • 前言 QuestPDF 是一個開源 .NET 庫,用於生成 PDF 文檔。使用了C# Fluent API方式可簡化開發、減少錯誤並提高工作效率。利用它可以輕鬆生成 PDF 報告、發票、導出文件等。 項目介紹 QuestPDF 是一個革命性的開源 .NET 庫,它徹底改變了我們生成 PDF 文檔的方 ...
  • 項目地址 項目後端地址: https://github.com/ZyPLJ/ZYTteeHole 項目前端頁面地址: ZyPLJ/TreeHoleVue (github.com) https://github.com/ZyPLJ/TreeHoleVue 目前項目測試訪問地址: http://tree ...
  • 話不多說,直接開乾 一.下載 1.官方鏈接下載: https://www.microsoft.com/zh-cn/sql-server/sql-server-downloads 2.在下載目錄中找到下麵這個小的安裝包 SQL2022-SSEI-Dev.exe,運行開始下載SQL server; 二. ...
  • 前言 隨著物聯網(IoT)技術的迅猛發展,MQTT(消息隊列遙測傳輸)協議憑藉其輕量級和高效性,已成為眾多物聯網應用的首選通信標準。 MQTTnet 作為一個高性能的 .NET 開源庫,為 .NET 平臺上的 MQTT 客戶端與伺服器開發提供了強大的支持。 本文將全面介紹 MQTTnet 的核心功能 ...
  • Serilog支持多種接收器用於日誌存儲,增強器用於添加屬性,LogContext管理動態屬性,支持多種輸出格式包括純文本、JSON及ExpressionTemplate。還提供了自定義格式化選項,適用於不同需求。 ...
  • 目錄簡介獲取 HTML 文檔解析 HTML 文檔測試參考文章 簡介 動態內容網站使用 JavaScript 腳本動態檢索和渲染數據,爬取信息時需要模擬瀏覽器行為,否則獲取到的源碼基本是空的。 本文使用的爬取步驟如下: 使用 Selenium 獲取渲染後的 HTML 文檔 使用 HtmlAgility ...
  • 1.前言 什麼是熱更新 游戲或者軟體更新時,無需重新下載客戶端進行安裝,而是在應用程式啟動的情況下,在內部進行資源或者代碼更新 Unity目前常用熱更新解決方案 HybridCLR,Xlua,ILRuntime等 Unity目前常用資源管理解決方案 AssetBundles,Addressable, ...
  • 本文章主要是在C# ASP.NET Core Web API框架實現向手機發送驗證碼簡訊功能。這裡我選擇是一個互億無線簡訊驗證碼平臺,其實像阿裡雲,騰訊雲上面也可以。 首先我們先去 互億無線 https://www.ihuyi.com/api/sms.html 去註冊一個賬號 註冊完成賬號後,它會送 ...
  • 通過以下方式可以高效,並保證數據同步的可靠性 1.API設計 使用RESTful設計,確保API端點明確,並使用適當的HTTP方法(如POST用於創建,PUT用於更新)。 設計清晰的請求和響應模型,以確保客戶端能夠理解預期格式。 2.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...