日韩成人免费在线_国产成人一二_精品国产免费人成电影在线观..._日本一区二区三区久久久久久久久不

當(dāng)前位置:首頁(yè) > 科技  > 軟件

說(shuō)一說(shuō) JavaScript 異步迭代器

來(lái)源: 責(zé)編: 時(shí)間:2024-02-29 14:43:58 246觀(guān)看
導(dǎo)讀你知道嗎?除了像Promise.finally這樣的 API 之外,ECMAScript 2018還為我們帶來(lái)了另一種處理迭代器的方式——異步迭代器。問(wèn)題假設(shè)現(xiàn)在我們正處于這樣一個(gè)情景:需要使用Node.js逐行讀取文件。Node有個(gè)API叫做readLine,它

你知道嗎?除了像Promise.finally這樣的 API 之外,ECMAScript 2018還為我們帶來(lái)了另一種處理迭代器的方式——異步迭代器。5sB28資訊網(wǎng)——每日最新資訊28at.com

問(wèn)題

假設(shè)現(xiàn)在我們正處于這樣一個(gè)情景:需要使用Node.js逐行讀取文件。Node有個(gè)API叫做readLine,它是一個(gè)包裝器,可用于逐行從輸入流中讀取數(shù)據(jù),不需要分析輸入緩沖區(qū)、也不需要將文本分解為小塊。5sB28資訊網(wǎng)——每日最新資訊28at.com

你可以像這樣監(jiān)聽(tīng):5sB28資訊網(wǎng)——每日最新資訊28at.com

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))

假設(shè)有這樣一個(gè)簡(jiǎn)單的文件:5sB28資訊網(wǎng)——每日最新資訊28at.com

line 1line 2line 3

如果我們?cè)趧?chuàng)建的文件上運(yùn)行代碼,那么就能在控制臺(tái)上逐行輸出。但是,使用事件并不是編寫(xiě)可維護(hù)代碼的最佳方法之一,因?yàn)槭录峭耆惒降模赡軙?huì)中斷代碼流——因?yàn)槭菬o(wú)序觸發(fā)的,并且只能通過(guò)偵聽(tīng)器分配操作。5sB28資訊網(wǎng)——每日最新資訊28at.com

解決方案

除了事件 API之外,readline還有async iterator。現(xiàn)在我們可以不通過(guò)line事件中的偵聽(tīng)器讀取,而是通過(guò)for關(guān)鍵字來(lái)讀取。5sB28資訊網(wǎng)——每日最新資訊28at.com

舉幾個(gè)使用for循環(huán)的例子。第一個(gè)是最常見(jiàn)的使用計(jì)數(shù)器和條件:5sB28資訊網(wǎng)——每日最新資訊28at.com

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

我們也可以使用for … in表示法讀取數(shù)組索引:5sB28資訊網(wǎng)——每日最新資訊28at.com

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

在前一種情況下,console.log輸出從1到6的數(shù)字,但是如果我們使用console.log (index),那么記錄的是數(shù)組的索引,從0到5的數(shù)字。5sB28資訊網(wǎng)——每日最新資訊28at.com

下面,我們使用for … of表示法,直接獲取數(shù)組的可枚舉屬性,即它的直接值:5sB28資訊網(wǎng)——每日最新資訊28at.com

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

注意,這些方法都是同步的。那么,如果我們有一系列promise,這時(shí)該如何按順序讀取呢?5sB28資訊網(wǎng)——每日最新資訊28at.com

假設(shè)我們還有另一個(gè)接口,它總是返回一個(gè)Promise。為了按順序解析promise,我們需要這樣做:5sB28資訊網(wǎng)——每日最新資訊28at.com

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

而現(xiàn)在,多虧異步可迭代對(duì)象(如readline)的魔力,我們可以執(zhí)行以下操作:5sB28資訊網(wǎng)——每日最新資訊28at.com

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()

注意,我們現(xiàn)在使用的是for、for await (const x of y)的新定義。5sB28資訊網(wǎng)——每日最新資訊28at.com

對(duì)于await和node.js

從10.x版開(kāi)始,Node.js運(yùn)行時(shí)原生支持for await表示法。如果你使用的是8.x或9.x版本,則需要使用--harmony_async_iteration標(biāo)志啟動(dòng)Javascript文件。遺憾的是,Node.js的版本6和版本7不支持異步迭代器。5sB28資訊網(wǎng)——每日最新資訊28at.com

為了理解異步迭代器的概念,首先我們需要知道迭代器的本質(zhì)。簡(jiǎn)而言之,迭代器是一個(gè)對(duì)象,公開(kāi)next()函數(shù),此函數(shù)返回另一個(gè)對(duì)象,其中{value: any, done: boolean}表示當(dāng)前迭代的值,done表示序列中是否還有其他值。5sB28資訊網(wǎng)——每日最新資訊28at.com

遍歷數(shù)組中所有項(xiàng)的迭代器示例如下:5sB28資訊網(wǎng)——每日最新資訊28at.com

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

就其本身而言,迭代器沒(méi)有實(shí)際用途,那么怎么辦呢?為此,我們需要iterable。iterable是一個(gè)對(duì)象,它有一個(gè)Symbol.iterator鍵,該鍵返回的函數(shù)返回迭代器:5sB28資訊網(wǎng)——每日最新資訊28at.com

// ... Iterator code here ...const iterable = {  [Symbol.iterator]: () => iterator}

現(xiàn)在我們可以正常使用迭代器了,通過(guò)for (const x of iterable),我們可以一個(gè)一個(gè)地迭代array中的所有值。5sB28資訊網(wǎng)——每日最新資訊28at.com

在后臺(tái),所有數(shù)組和對(duì)象都有Symbol.iterator,這樣就可以執(zhí)行for (let x of [1,2,3])并返回我們想要的值。5sB28資訊網(wǎng)——每日最新資訊28at.com

我們可以看到,異步迭代器與迭代器完全相同,不同之處在于iterable擁有的是Symbol.asyncIterator,而不是Symbol.iterator,擁有的是解析為具有相同簽名對(duì)象的Promise,而不是返回{value, done}的對(duì)象。5sB28資訊網(wǎng)——每日最新資訊28at.com

讓我們把上面的迭代器變成一個(gè)異步迭代器:5sB28資訊網(wǎng)——每日最新資訊28at.com

const array = [1,2,3]let index = 0const asyncIterator = {  next: () => {  if (index >= array.length) return Promise.resolve({done: true})  return Promise.resolve({value: array[index++], done: false})  }}const asyncIterable = {  [Symbol.asyncIterator]: () => asyncIterator}

異步迭代

我們可以通過(guò)調(diào)用next()函數(shù)來(lái)手動(dòng)迭代迭代器:5sB28資訊網(wǎng)——每日最新資訊28at.com

// ... 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,但請(qǐng)記住,關(guān)鍵字await只能在異步函數(shù)中使用,所以我們需要有類(lèi)似這樣的代碼:5sB28資訊網(wǎng)——每日最新資訊28at.com

// ... Code above ...async function iterate () {  for await (const num of asyncIterable) console.log(num)}iterate() // 1, 2, 3

但是,由于Node 8.x和9.x這樣的老版本不支持異步迭代器,為了在這些版本中使用異步迭代器,我們可以簡(jiǎn)單地從對(duì)象中提取next并手動(dòng)遍歷:5sB28資訊網(wǎng)——每日最新資訊28at.com

// ... 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更干凈、更簡(jiǎn)潔,因?yàn)樗男袨轭?lèi)似于常規(guī)循環(huán),而且,除了更易于理解之外,還可以通過(guò)done鍵自行檢查迭代器的結(jié)束。5sB28資訊網(wǎng)——每日最新資訊28at.com

處理錯(cuò)誤

如果promise在迭代器中被拒絕,會(huì)發(fā)生什么?好吧,和任何被拒絕的promise一樣,通過(guò)簡(jiǎn)單的try/catch就可以來(lái)捕獲錯(cuò)誤(因?yàn)槲覀兪褂玫氖莂wait):5sB28資訊網(wǎng)——每日最新資訊28at.com

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()

回退

關(guān)于異步迭代器,非常有趣的一點(diǎn)是,它們有Symbol.iterator的回退,這意味著你也可以將它與常規(guī)迭代器一起使用,例如,有這樣一個(gè)promise數(shù)組:5sB28資訊網(wǎng)——每日最新資訊28at.com

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

異步生成器

在大多數(shù)情況下,迭代器和異步迭代器可以創(chuàng)建自生成器。5sB28資訊網(wǎng)——每日最新資訊28at.com

生成器是允許暫停和恢復(fù)執(zhí)行的函數(shù),因此可以操作執(zhí)行,然后通過(guò)next()函數(shù)獲取下一個(gè)值。5sB28資訊網(wǎng)——每日最新資訊28at.com

異步生成器的行為類(lèi)似于異步迭代器,但你必須手動(dòng)實(shí)現(xiàn)停止機(jī)制,例如,這里我們構(gòu)建一個(gè)用于git提交的隨機(jī)消息生成器:5sB28資訊網(wǎng)——每日最新資訊28at.com

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  }}

注意,在任何時(shí)候都不會(huì)返回{value, done}對(duì)象,因此循環(huán)無(wú)法知道執(zhí)行何時(shí)完成。這時(shí)我們可以實(shí)現(xiàn)這樣的函數(shù):5sB28資訊網(wǎng)——每日最新資訊28at.com

// Previous Codeasync 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.

用例

再來(lái)一個(gè)更有趣的示例,為一個(gè)真實(shí)用例構(gòu)建異步迭代器。目前,適用于Node.js的Oracle數(shù)據(jù)庫(kù)驅(qū)動(dòng)程序支持resultSet API,因此可以在數(shù)據(jù)庫(kù)上執(zhí)行查詢(xún)并返回,而數(shù)據(jù)流則可以通過(guò)getRow()方法逐個(gè)讀取。5sB28資訊網(wǎng)——每日最新資訊28at.com

要?jiǎng)?chuàng)建resultSet,我們需要在數(shù)據(jù)庫(kù)中執(zhí)行查詢(xún),如下所示:5sB28資訊網(wǎng)——每日最新資訊28at.com

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有一個(gè)名為getRow()的方法,這個(gè)方法從數(shù)據(jù)庫(kù)中返回要獲取的下一行的Promise。我們可以創(chuàng)建一個(gè)逐行返回此resultSet的光標(biāo)。下面讓我們創(chuàng)建Cursor類(lèi):5sB28資訊網(wǎng)——每日最新資訊28at.com

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

查看光標(biāo)是否接收到它應(yīng)該處理的resultSet,并將其存儲(chǔ)在當(dāng)前狀態(tài)。因此,我們需要更改之前的方法,以便返回光標(biāo)而不是resultSet:5sB28資訊網(wǎng)——每日最新資訊28at.com

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()

這樣,我們就可以遍歷所有返回的行,不需要單獨(dú)的Promise解析。5sB28資訊網(wǎng)——每日最新資訊28at.com

結(jié)論

異步迭代器非常強(qiáng)大,尤其是在Javascript等動(dòng)態(tài)和異步語(yǔ)言中。有了它們,我們就可以將復(fù)雜的執(zhí)行變成簡(jiǎn)單的代碼,從而向用戶(hù)隱藏復(fù)雜性,增加友好的用戶(hù)體驗(yàn)。5sB28資訊網(wǎng)——每日最新資訊28at.com

本文鏈接:http://m.www897cc.com/showinfo-26-75366-0.html說(shuō)一說(shuō) JavaScript 異步迭代器

聲明:本網(wǎng)頁(yè)內(nèi)容旨在傳播知識(shí),若有侵權(quán)等問(wèn)題請(qǐng)及時(shí)與本網(wǎng)聯(lián)系,我們將在第一時(shí)間刪除處理。郵件:2376512515@qq.com

上一篇: 2023年需求最高的八大編程語(yǔ)言

下一篇: Kafka 為什么這么快?

標(biāo)簽:
  • 熱門(mén)焦點(diǎn)
Top 日韩成人免费在线_国产成人一二_精品国产免费人成电影在线观..._日本一区二区三区久久久久久久久不
久久中文久久字幕| 亚洲欧美日韩国产中文| 国产一区再线| 亚洲成人资源网| 99在线精品视频在线观看| 亚洲女人天堂av| 久久青草欧美一区二区三区| 欧美好骚综合网| 国产精品久久77777| 国产在线视频欧美| 亚洲精品网址在线观看| 亚洲欧美日韩国产精品| 久久视频这里只有精品| 欧美日韩高清一区| 国产亚洲人成a一在线v站| 亚洲国产精品ⅴa在线观看| 亚洲视频每日更新| 久久人人爽人人爽爽久久| 欧美区国产区| 国产一区在线播放| 一本色道精品久久一区二区三区| 欧美一区在线直播| 欧美国产欧美亚洲国产日韩mv天天看完整 | 久久av最新网址| 欧美大尺度在线| 国产精品一区在线观看| 亚洲国产日韩精品| 午夜在线视频观看日韩17c| 欧美成人午夜激情视频| 国产日产高清欧美一区二区三区| 亚洲精品乱码久久久久久| 欧美一区二区成人| 欧美日韩国产麻豆| 黄色成人免费网站| 亚洲欧美日韩成人高清在线一区| 欧美电影在线观看| 国产一区二区三区在线观看免费| 中文日韩电影网站| 欧美国产极速在线| 激情欧美一区二区三区| 亚洲欧美日韩在线播放| 欧美日韩亚洲视频| 亚洲国产精品久久久久久女王| 欧美亚洲免费电影| 国产精品爱久久久久久久| 亚洲国产精品小视频| 久久国产夜色精品鲁鲁99| 国产精品地址| 日韩视频在线免费| 免费看av成人| 国产一区日韩一区| 亚洲欧美国产另类| 欧美日韩综合视频网址| 在线欧美日韩| 久久久噜噜噜久久中文字幕色伊伊| 国产精品视频999| 亚洲网在线观看| 欧美人在线视频| 狂野欧美激情性xxxx| 国产精品综合色区在线观看| 99视频一区二区| 欧美国产精品| 亚洲第一网站| 久久色在线观看| 国产一区视频在线观看免费| 欧美在线日韩| 国产亚洲精品成人av久久ww| 午夜视黄欧洲亚洲| 国产精品人成在线观看免费| 亚洲视频二区| 国产精品qvod| 亚洲男女自偷自拍| 国产精品久久久久av| 中国成人亚色综合网站| 欧美日韩在线高清| 夜夜嗨av一区二区三区中文字幕| 欧美伦理视频网站| 99精品视频免费全部在线| 欧美精品在线一区| 亚洲美女电影在线| 欧美久久一级| 日韩午夜在线电影| 欧美日韩理论| 亚洲视频免费观看| 国产精品久久久一区麻豆最新章节| 一区二区日韩精品| 欧美色图麻豆| 亚洲一区综合| 国产婷婷色一区二区三区| 久久久久久久尹人综合网亚洲 | 国产精品福利在线观看| 亚洲综合成人婷婷小说| 国产精品一卡| 欧美一区二区在线看| 国产亚洲在线观看| 久久亚洲春色中文字幕| 亚洲高清一区二| 欧美另类videos死尸| 亚洲视频在线观看免费| 国产精品一区二区三区四区五区| 久久av在线看| 亚洲福利视频专区| 欧美美女bb生活片| 亚洲永久免费精品| 国产一区二区三区四区三区四| 久久久精品网| 亚洲精品国精品久久99热| 欧美四级伦理在线| 欧美在线日韩| 亚洲国产欧美不卡在线观看| 欧美日韩精品久久久| 午夜精品www| 禁断一区二区三区在线| 欧美激情中文不卡| 亚洲欧美日韩一区在线观看| 韩日在线一区| 欧美日韩精品二区第二页| 亚洲欧美久久久久一区二区三区| 国产一区二区三区久久 | 午夜精品av| 在线精品视频一区二区| 欧美日韩在线第一页| 久久高清一区| 亚洲日韩欧美视频| 国产精品色婷婷| 噜噜噜噜噜久久久久久91| 9i看片成人免费高清| 国产亚洲成年网址在线观看| 欧美成人69av| 亚洲欧美一区二区三区极速播放 | 欧美在线电影| 亚洲破处大片| 国产精品一区一区| 男男成人高潮片免费网站| 中国成人亚色综合网站| 国产在线国偷精品产拍免费yy| 欧美激情综合五月色丁香| 性色一区二区| 亚洲免费播放| 黑人操亚洲美女惩罚| 欧美性猛交xxxx乱大交蜜桃| 久久久噜噜噜久久| 亚洲天堂成人| 亚洲国产成人午夜在线一区| 国产精品视频内| 欧美大秀在线观看| 欧美一区免费视频| 一区二区免费在线播放| 在线观看中文字幕不卡| 国产毛片一区| 欧美日韩午夜精品| 麻豆成人在线观看| 午夜综合激情| 一本大道久久a久久综合婷婷| 国外成人免费视频| 国产精品久久久久久久一区探花 | 欧美性猛交99久久久久99按摩| 久久综合色综合88| 先锋影音国产一区| 日韩一级二级三级| 在线免费不卡视频| 国产欧美一区在线| 欧美性片在线观看| 欧美国产亚洲另类动漫| 久久久久www| 亚洲欧美日韩国产一区| 夜夜嗨av一区二区三区免费区| 樱花yy私人影院亚洲| 国产日本欧洲亚洲| 国产精品久久久久久久久搜平片| 欧美大尺度在线| 久久久www| 午夜欧美大片免费观看| 中文av一区二区| 亚洲激情网站| 国产自产2019最新不卡| 国产欧美日韩| 国产精品日韩精品| 欧美日一区二区在线观看| 欧美精品色一区二区三区| 免费观看成人| 久久网站热最新地址| 欧美一区精品| 午夜免费在线观看精品视频| 亚洲视频在线观看三级| 日韩一级大片| 亚洲精品乱码| 亚洲欧洲精品成人久久奇米网| 一区二区在线免费观看| 黑丝一区二区| 国产一区二区三区在线播放免费观看| 欧美亚洲第一页| 欧美亚州一区二区三区| 欧美视频精品一区| 欧美日韩a区| 亚洲日本免费| 亚洲日韩第九十九页| 亚洲电影成人| 亚洲国产欧美日韩| 亚洲高清123| 亚洲国产美女精品久久久久∴| 在线不卡免费欧美| 在线观看欧美激情| 亚洲第一精品夜夜躁人人躁|