精品欧美一区二区三区在线观看 _久久久久国色av免费观看性色_国产精品久久在线观看_亚洲第一综合网站_91精品又粗又猛又爽_小泽玛利亚一区二区免费_91亚洲精品国偷拍自产在线观看 _久久精品视频在线播放_美女精品久久久_欧美日韩国产成人在线

說一說 JavaScript 異步迭代器

開發 前端
異步迭代器非常強大,尤其是在Javascript等動態和異步語言中。有了它們,我們就可以將復雜的執行變成簡單的代碼,從而向用戶隱藏復雜性,增加友好的用戶體驗。

你知道嗎?除了像Promise.finally這樣的 API 之外,ECMAScript 2018還為我們帶來了另一種處理迭代器的方式——異步迭代器。

問題

假設現在我們正處于這樣一個情景:需要使用Node.js逐行讀取文件。Node有個API叫做readLine,它是一個包裝器,可用于逐行從輸入流中讀取數據,不需要分析輸入緩沖區、也不需要將文本分解為小塊。

你可以像這樣監聽:

const fs = require('fs')
const readline = require('readline')
const reader = readline.createInterface({
  input: fs.createReadStream('./file.txt'),
  crlfDelay: Infinity
})

reader.on('line', (line) => console.log(line))

假設有這樣一個簡單的文件:

line 1
line 2
line 3

如果我們在創建的文件上運行代碼,那么就能在控制臺上逐行輸出。但是,使用事件并不是編寫可維護代碼的最佳方法之一,因為事件是完全異步的,可能會中斷代碼流——因為是無序觸發的,并且只能通過偵聽器分配操作。

解決方案

除了事件 API之外,readline還有async iterator。現在我們可以不通過line事件中的偵聽器讀取,而是通過for關鍵字來讀取。

舉幾個使用for循環的例子。第一個是最常見的使用計數器和條件:

for (let x = 0; x < array.length; x++) {
  // Code here
}

我們也可以使用for … in表示法讀取數組索引:

const a = [1,2,3,4,5,6]
for (let index in a) {
  console.log(a[index])
}

在前一種情況下,console.log輸出從1到6的數字,但是如果我們使用console.log (index),那么記錄的是數組的索引,從0到5的數字。

下面,我們使用for … of表示法,直接獲取數組的可枚舉屬性,即它的直接值:

const a = [1,2,3,4,5,6]

for (let item of a) {
  console.log(item)
}

注意,這些方法都是同步的。那么,如果我們有一系列promise,這時該如何按順序讀取呢?

假設我們還有另一個接口,它總是返回一個Promise。為了按順序解析promise,我們需要這樣做:

async function readLine (files) {
  for (const file of files) {
    const line = await readFile(file) // Imagine readFile is our cursor
    console.log(line)
  }
}

而現在,多虧異步可迭代對象(如readline)的魔力,我們可以執行以下操作:

const fs = require('fs')
const readline = require('readline')
const reader = readline.createInterface({
  input: fs.createReadStream('./xpto.txt'),
  crlfDelay: Infinity
})

async function read () {
  for await (const line of reader) {
    console.log(line)
  }
}

read()

注意,我們現在使用的是for、for await (const x of y)的新定義。

對于await和node.js

從10.x版開始,Node.js運行時原生支持for await表示法。如果你使用的是8.x或9.x版本,則需要使用--harmony_async_iteration標志啟動Javascript文件。遺憾的是,Node.js的版本6和版本7不支持異步迭代器。

為了理解異步迭代器的概念,首先我們需要知道迭代器的本質。簡而言之,迭代器是一個對象,公開next()函數,此函數返回另一個對象,其中{value: any, done: boolean}表示當前迭代的值,done表示序列中是否還有其他值。

遍歷數組中所有項的迭代器示例如下:

const array = [1,2,3]
let index = 0

const iterator = {
  next: () => {
    if (index >= array.length) return { done: true }
    return {
      value: array[index++],
      done: false
    }
  }
}

就其本身而言,迭代器沒有實際用途,那么怎么辦呢?為此,我們需要iterable。iterable是一個對象,它有一個Symbol.iterator鍵,該鍵返回的函數返回迭代器:

// ... Iterator code here ...

const iterable = {
  [Symbol.iterator]: () => iterator
}

現在我們可以正常使用迭代器了,通過for (const x of iterable),我們可以一個一個地迭代array中的所有值。

在后臺,所有數組和對象都有Symbol.iterator,這樣就可以執行for (let x of [1,2,3])并返回我們想要的值。

我們可以看到,異步迭代器與迭代器完全相同,不同之處在于iterable擁有的是Symbol.asyncIterator,而不是Symbol.iterator,擁有的是解析為具有相同簽名對象的Promise,而不是返回{value, done}的對象。

讓我們把上面的迭代器變成一個異步迭代器:

const array = [1,2,3]
let index = 0

const asyncIterator = {
  next: () => {
  if (index >= array.length) return Promise.resolve({done: true})
  return Promise.resolve({value: array[index++], done: false})
  }
}

const asyncIterable = {
  [Symbol.asyncIterator]: () => asyncIterator
}

異步迭代

我們可以通過調用next()函數來手動迭代迭代器:

// ... Async iterator Code here ...

async function manual () {
  const promise = asyncIterator.next() // Promise
  await p // Object { value: 1, done: false }
  await asyncIterator.next() // Object { value: 2, done: false }
  await asyncIterator.next() // Object { value: 3, done: false }
  await asyncIterator.next() // Object { done: true }
}

為了遍歷異步迭代器,我們需要使用for await,但請記住,關鍵字await只能在異步函數中使用,所以我們需要有類似這樣的代碼:

// ... Code above ...

async function iterate () {
  for await (const num of asyncIterable) console.log(num)
}

iterate() // 1, 2, 3

但是,由于Node 8.x和9.x這樣的老版本不支持異步迭代器,為了在這些版本中使用異步迭代器,我們可以簡單地從對象中提取next并手動遍歷:

// ... Async Iterator Code here ...

async function iterate () {
  const {next} = asyncIterable[Symbol.asyncIterator]() // we take the next iterator function

  for (let {value, done} = await next(); !done; {value, done} = await next()) {
    console.log(value)
  }
}

注意,for await更干凈、更簡潔,因為它的行為類似于常規循環,而且,除了更易于理解之外,還可以通過done鍵自行檢查迭代器的結束。

處理錯誤

如果promise在迭代器中被拒絕,會發生什么?好吧,和任何被拒絕的promise一樣,通過簡單的try/catch就可以來捕獲錯誤(因為我們使用的是await):

const asyncIterator = { next: () => Promise.reject('Error') }
const asyncIterable = { [Symbol.asyncIterator]: () => asyncIterator 

async function iterate () {
  try {
    for await (const num of asyncIterable) {}
  } catch (e) {
    console.log(e.message)
  }
}

iterate()

回退

關于異步迭代器,非常有趣的一點是,它們有Symbol.iterator的回退,這意味著你也可以將它與常規迭代器一起使用,例如,有這樣一個promise數組:

const promiseArray = [
  fetch('https://lsantos.dev'),
  fetch('https://lsantos.me')
]

async function iterate () {
  for await (const response of promiseArray) console.log(response.status)
}

iterate() // 200, 200

異步生成器

在大多數情況下,迭代器和異步迭代器可以創建自生成器。

生成器是允許暫停和恢復執行的函數,因此可以操作執行,然后通過next()函數獲取下一個值。

異步生成器的行為類似于異步迭代器,但你必須手動實現停止機制,例如,這里我們構建一個用于git提交的隨機消息生成器:

async function* gitCommitMessageGenerator () {
  const url = 'https://whatthecommit.com/index.txt'

  while (true) {
    const response = await fetch(url)
    yield await response.text() // We return the value
  }
}

注意,在任何時候都不會返回{value, done}對象,因此循環無法知道執行何時完成。這時我們可以實現這樣的函數:

// Previous Code
async function getCommitMessages (times) {
  let execution = 1
  for await (const message of gitCommitMessageGenerator()) {
    console.log(message)
    if (execution++ >= times) break
  }
}

getCommitMessages(5)
// I'll explain this when I'm sober .. or revert it
// Never before had a small typo like this one caused so much damage.
// For real, this time.
// Too lazy to write descriptive message
// Ugh. Bad rebase.

用例

再來一個更有趣的示例,為一個真實用例構建異步迭代器。目前,適用于Node.js的Oracle數據庫驅動程序支持resultSet API,因此可以在數據庫上執行查詢并返回,而數據流則可以通過getRow()方法逐個讀取。

要創建resultSet,我們需要在數據庫中執行查詢,如下所示:

const oracle = require('oracledb')
const options = {
  user: 'example',
  password: 'example123',
  connectString: 'string'
}

async function start () {
  const connection = await oracle.getConnection(options)
  const { resultSet } = await connection.execute('query', [], { outFormat: oracle.OBJECT, resultSet: true })
  return resultSet
}

start().then(console.log)

resultSet有一個名為getRow()的方法,這個方法從數據庫中返回要獲取的下一行的Promise。我們可以創建一個逐行返回此resultSet的光標。下面讓我們創建Cursor類:

class Cursor {
  constructor(resultSet) {
    this.resultSet = resultSet
  }

  getIterable() {
    return {
      [Symbol.asyncIterator]: () => this._buildIterator()
    }
  }

  _buildIterator() {
    return {
      next: () => this.resultSet.getRow().then((row) => ({ value: row, done: row === undefined }))
    }
  }
}

module.exports = Cursor

查看光標是否接收到它應該處理的resultSet,并將其存儲在當前狀態。因此,我們需要更改之前的方法,以便返回光標而不是resultSet:

const oracle = require('oracledb')
const options = {
  user: 'example',
  password: 'example123',
  connectString: 'string'
}
async function getResultSet() {
  const connection = await oracle.getConnection(options)
  const { resultSet } = await connection.execute('query', [], { outFormat: oracle.OBJECT, resultSet: true })
  return resultSet
}

async function start() {
  const resultSet = await getResultSet()
  const cursor = new Cursor(resultSet)

  for await (const row of cursor.getIterable()) {
    console.log(row)
  }
}

start()

這樣,我們就可以遍歷所有返回的行,不需要單獨的Promise解析。

結論

異步迭代器非常強大,尤其是在Javascript等動態和異步語言中。有了它們,我們就可以將復雜的執行變成簡單的代碼,從而向用戶隱藏復雜性,增加友好的用戶體驗。

責任編輯:武曉燕 來源: 前端新世界
相關推薦

2021-06-27 21:10:12

Linux 進程控制

2021-07-31 22:20:00

線程池系統參數

2011-07-26 09:04:44

MySQL Repli數據庫負載均衡

2020-10-30 10:38:50

Python開發語法

2011-07-25 13:34:08

ORACLEFLASHBACK T

2021-01-06 17:28:00

MySQL數據庫緩存池

2015-10-23 11:40:08

SaaS應用開發

2023-12-29 10:28:24

SPIJava靈活性

2011-07-25 17:38:32

數據存儲一致性模型

2018-01-17 15:15:22

虛擬化IO半虛擬化

2018-04-09 15:10:50

測試方法新手軟件

2021-03-09 10:05:06

5G運營商技術

2023-03-13 22:09:59

JavaSpring機制

2024-10-24 08:31:26

2020-11-24 08:00:22

JavaScript對象迭代器

2010-11-17 10:20:46

求職

2021-03-04 23:12:57

Node.js異步迭代器開發

2021-09-15 06:55:34

異步LinqC#

2023-10-26 00:41:46

臟讀數據幻讀

2020-12-08 06:28:47

Node.js異步迭代器
點贊
收藏

51CTO技術棧公眾號

91精品国产综合久久精品图片| 久久五月婷婷丁香社区| 中文字幕在线国产精品| 天天操精品视频| 888av在线视频| 欧美激情一区二区| 成人午夜国产| 日韩一区有码在线| 久久66热这里只有精品| 亚洲无码久久久久| 最新成人av网站| 日韩在线观看免费全| 日韩精品视频一区二区| 香蕉成人在线| 91久久精品一区二区二区| 超碰97免费观看| 加勒比一区二区三区在线| 国产精品白丝jk黑袜喷水| 日本乱人伦a精品| 欧美极品视频在线观看| 成人av动漫在线观看| 亚洲国产另类久久精品| 国产又粗又长又爽又黄的视频| 中文在线免费二区三区| 亚洲一区二区三区影院| 亚洲一区bb| 国产黄色在线| 97se亚洲国产综合自在线不卡 | 久久国产欧美日韩精品| 性金发美女69hd大尺寸| 2021亚洲天堂| 天天久久综合| 日韩中文字幕网| 久久精品国产亚洲AV熟女| 99久久香蕉| 91精品免费在线| 亚洲天堂2018av| 亚洲第一会所| 在线观看中文字幕不卡| 国产免费成人在线| 成人一级福利| 丁香五六月婷婷久久激情| 九九热只有这里有精品| 亚洲精品白浆| 亚洲综合在线观看视频| 男人j进女人j| √天堂8在线网| 亚洲男帅同性gay1069| 一区二区三区四区欧美| 在线看黄色av| 国产精品久久久久久久午夜片| 日韩高清国产一区在线观看| 国产在线视频福利| 国产三级欧美三级日产三级99| 青青草原亚洲| 国产污视频在线| 欧美国产日本韩| 丝袜美腿玉足3d专区一区| 成人亚洲综合天堂| 中文无字幕一区二区三区| 亚洲精品一卡二卡三卡四卡| 色网站免费在线观看| 国产精品久久久久久久久动漫| 亚洲精品tv久久久久久久久| 日本在线视频网| 亚洲色图制服诱惑| 日韩一级性生活片| 蜜桃在线视频| 色94色欧美sute亚洲13| 亚洲综合婷婷久久| 国产精品一级在线观看| 欧美不卡一区二区三区| 强迫凌虐淫辱の牝奴在线观看| 精品国产午夜肉伦伦影院| 日韩高清中文字幕| 日本综合在线观看| 综合天堂av久久久久久久| 欧美精品videos| 无码人妻aⅴ一区二区三区有奶水| 日韩成人免费电影| 91在线精品视频| 人妻妺妺窝人体色www聚色窝| 91在线云播放| 宅男在线精品国产免费观看| 性欧美videoshd高清| 亚欧色一区w666天堂| 毛片av免费在线观看| 2020国产精品小视频| 精品精品欲导航| www.99热| 伊人影院久久| 国产日韩在线一区| 日日躁夜夜躁白天躁晚上躁91| 国产午夜精品美女毛片视频| 色婷婷777777仙踪林| 77thz桃花论族在线观看| 欧美性色综合网| 成年人看片网站| 国产一区网站| 欧美激情在线狂野欧美精品| 久久影视中文字幕| 成人中文字幕在线| 亚洲一区二区精品在线| 自拍视频在线看| 日韩三级视频中文字幕| 欧美三级视频网站| 精品91久久久久| 成人女保姆的销魂服务| 免费国产在线视频| 亚洲一区二区精品视频| 97超碰人人爽| 精品一区欧美| 97久久超碰福利国产精品…| 国产精品自拍电影| 国产午夜精品一区二区三区嫩草| 99久久免费观看| 国产精品亚洲四区在线观看| 国产一区二区激情| 国语对白永久免费| 成人永久免费视频| 九一免费在线观看| 成人国产激情在线| 亚洲成年网站在线观看| 国产三级国产精品国产国在线观看| 老牛影视一区二区三区| 精品不卡在线| heyzo一区| 日韩精品中文字幕在线一区| 亚洲二区在线播放| 奇米综合一区二区三区精品视频| 免费国产一区| 一个人www视频在线免费观看| 欧美大片一区二区三区| 天天色影综合网| 久久99国产精品免费| 日韩欧美一区二区三区四区五区| 亚洲欧美韩国| 精品香蕉在线观看视频一| 五月天婷婷综合网| 99国产精品久久久久久久久久久| 波多野结衣综合网| 韩国女主播一区二区三区| 欧美激情精品久久久久久黑人| 国产男女裸体做爰爽爽| 亚洲欧洲性图库| 中文字幕色网站| 亚洲破处大片| 懂色av一区二区三区在线播放| 在线欧美三级| 亚洲а∨天堂久久精品9966| 国产午夜福利精品| 91免费在线播放| 欧美色图另类小说| 精品一区毛片| 国产精品一区二区三区成人| 日韩精品毛片| 日韩一级黄色片| 久久久久久国产精品免费播放| 成人性视频网站| 欧美日韩成人免费视频| 最新国产一区| 国产精品一区电影| 八戒八戒神马在线电影| 欧美xxxx在线观看| 成年人免费看毛片| 国产日产精品1区| 91国产精品视频在线观看| 色88久久久久高潮综合影院| 亚洲jizzjizz日本少妇| 男女免费观看在线爽爽爽视频| 亚洲高清不卡av| 亚洲GV成人无码久久精品| 中文字幕第一区二区| 久久精品亚洲天堂| 国产日韩高清一区二区三区在线| 日本一区高清不卡| 亚洲精品一区二区在线播放∴| 欧美极品少妇xxxxⅹ喷水| 偷拍自拍在线| 欧美人妖巨大在线| 久久网一区二区| 国产女同互慰高潮91漫画| 奇米777在线视频| 国产一级久久| 中文字幕一区二区三区四区五区六区| 中文字幕区一区二区三| 国产成人福利视频| 伊人影院在线视频| 国产亚洲精品va在线观看| 国产黄色小视频在线观看| 福利一区福利二区微拍刺激| 你懂得视频在线观看| 成人av网在线| 欧美三级午夜理伦三级富婆| 亚洲国产精品第一区二区| 日韩精品一区二区三区丰满| 亚洲综合网站| 国产精品久久久亚洲| 黄页网站在线| 日韩在线视频二区| 婷婷国产在线| 欧美日韩在线免费视频| 日韩黄色一级大片| 亚洲激情第一区| 日本免费www| 99re6这里只有精品视频在线观看| 日韩av.com| 天堂影院一区二区| 久久久久免费看黄a片app| 亚洲精品小说| 日韩中文字幕av在线| 中文字幕+乱码+中文| а天堂中文最新一区二区三区| www.久久色.com| 欧洲伦理片一区 二区 三区| 欧美不卡在线视频| 国产精品国产av| 欧美中文字幕一二三区视频| 日韩网红少妇无码视频香港| 一区二区三区日韩在线观看| 国产一区在线观看免费| 久久久久久久久久久电影| 国产精品久久久久久亚洲色| 国产一区二区三区av电影| 欧美午夜aaaaaa免费视频| 蘑菇福利视频一区播放| 日本手机在线视频| 欧美在线三区| 最新视频 - x88av| 日韩久久久久| 亚洲一区二区三区精品视频| 精品一区电影| 欧洲久久久久久| 国产成人短视频在线观看| 久中文字幕一区| 亚洲专区视频| 久久久久久亚洲精品不卡4k岛国 | 久久国产精品 国产精品| youjizz亚洲| 国产经典一区二区三区| 亚洲大奶少妇| 99www免费人成精品| 精品国产一区二| 成人欧美一区二区三区在线| 色噜噜成人av在线| 国产精品一区二区三| 日韩成人综合网| 成人国产精品色哟哟| 99久久99九九99九九九| 91免费看片在线| 91精品国产自产在线丝袜啪 | 红桃成人av在线播放| 欧美一区二区三区成人久久片| 美女久久99| 日韩资源av在线| 99国产**精品****| 欧美少妇一区二区三区| 国产一区欧美| 日本人体一区二区| 欧美亚洲自偷自偷| 三级在线免费看| 久久精品国产久精国产爱| 三级一区二区三区| 国产福利不卡视频| 亚洲精品第二页| 久久亚洲二区三区| 欧美自拍偷拍网| 亚洲美女在线一区| 成年人午夜视频| 在线观看亚洲精品| 国产极品久久久| 亚洲国产一区二区三区四区| 精品无人乱码| 久久九九国产精品怡红院 | 黄色一区二区三区四区| 日韩小视频在线播放| 日韩av高清在线观看| 国产精品igao网网址不卡| 成人av在线一区二区| 免费看黄色的视频| 亚洲男帅同性gay1069| 国产精品国产三级国产专区52| 欧美亚洲愉拍一区二区| va婷婷在线免费观看| 精品视频久久久久久久| 三级外国片在线观看视频| 国内精品小视频在线观看| 欧美成人黑人| 91亚洲精品丁香在线观看| 偷拍自拍一区| 在线观看视频黄色| 六月天综合网| a级大片免费看| 国产欧美日韩精品在线| 免费在线观看av网址| 欧美在线高清视频| 亚洲乱码在线观看| 在线播放日韩精品| 国产在线88av| 亚洲xxxxx性| 国产精品羞羞答答在线观看| 九一免费在线观看| 日本不卡高清视频| 亚洲av网址在线| 亚洲视频一二三| 尤物视频免费观看| 亚洲成人网久久久| 麻豆最新免费在线视频| 国产99视频在线观看| 综合视频一区| 黄色高清视频网站| 日韩经典中文字幕一区| 国产一卡二卡三卡四卡| 综合久久综合久久| 探花国产精品一区二区| 精品一区二区三区四区在线| 日本在线视频www鲁啊鲁| 国产精品普通话| 天天躁日日躁狠狠躁欧美| 国产美女作爱全过程免费视频| 久久国产精品第一页| 亚洲一区二区自偷自拍 | 亚洲一区二区三区乱码aⅴ| 红桃成人av在线播放| 国产在线观看福利| 粉嫩一区二区三区性色av| 婷婷伊人五月天| 777午夜精品免费视频| 国产精品久久久久一区二区国产| 欧美综合一区第一页| 红杏一区二区三区| 欧美激情亚洲天堂| 韩日欧美一区二区三区| 亚洲女人毛茸茸高潮| 日本道在线观看一区二区| 日本国产在线| 热久久免费视频精品| 青青草久久爱| 日本在线xxx| 91蝌蚪国产九色| av大全在线观看| 日韩精品在线观| 亚洲精品中文字幕| 欧洲亚洲一区| 日本成人中文字幕在线视频| 国产午夜精品福利视频| 欧美三级日本三级少妇99| 尤物网在线观看| 91精品在线国产| 午夜激情一区| 少妇伦子伦精品无吗| 亚洲一区av在线| 日韩中文字幕影院| 欧美性在线观看| 成人精品天堂一区二区三区| 中文字幕成人免费视频| 亚洲精品国产精品乱码不99| 亚洲av无码一区二区乱子伦| 欧美精品videossex88| 欧美电影在线观看完整版| 国产精品欧美激情在线观看| 久久精品人人爽人人爽| 中文字幕资源网| 欧美乱人伦中文字幕在线| 国产精品对白| 日韩有码免费视频| 亚洲欧洲日韩一区二区三区| 精品人妻久久久久一区二区三区| 午夜精品一区二区三区在线视频 | 久久精品福利| 精品国产成人av在线免| 国产精品久久久久久亚洲毛片| 国产成人久久精品77777综合 | 精品国产欧美一区二区五十路 | 欧美xxxxx牲另类人与| 三妻四妾的电影电视剧在线观看| 午夜精品视频在线观看一区二区| 国产自产高清不卡| 激情综合网五月婷婷| 亚洲一二三在线| 91大神精品| 午夜免费福利在线| 亚洲精品国产精华液| 无码国产色欲xxxx视频| 国产精品香蕉av| 亚洲片区在线| 精品视频第一页| 亚洲国产成人av在线| 91九色综合| 免费av手机在线观看| 国产精品色一区二区三区| 丰满肥臀噗嗤啊x99av| 国产精品第8页| 国产精品成人一区二区网站软件| 非洲一级黄色片| 精品成人私密视频| 日本国产一区| 无码人妻精品一区二区三区在线| 亚洲天堂成人在线观看| 青青青免费视频在线2|