成人免费xxxxx在线视频软件_久久精品久久久_亚洲国产精品久久久_天天色天天色_亚洲人成一区_欧美一级欧美三级在线观看

JavaScript 中的生成器有什么用?

開發 前端
今天我們要講的是JavaScript中一個不太常用的Generator語法。我很少看到有人在實際項目開發中使用它。

今天我們要講的是JavaScript中一個不太常用的Generator語法。我很少看到有人在實際項目開發中使用它。 

可能是因為它的語法比較復雜,而且是 async/awiatcan ,所以人們很少使用它。然而,Generatorit 仍然是。

今天我們就從基礎開始練習Generator。

Generator介紹

JavaScript GeneratorE6是引入的一種新型函數,可以生成多個值序列,可以暫停和恢復執行,使我們能夠更簡單、高效地實現迭代器。

如果我們看到一個函數后面跟著一個 * 符號,那么它就是一個 Generatorfunction :

function* myGenerator() {
  // Generator function
}

GeneratorFunctions 可以使用yield語句來定義要生成的值的序列。 

每當yield語句時,Generator函數就會暫停執行并返回一個包含當前生成值的對象,然后執行流程將暫停,直到下一次調用generator函數。 

它的返回值是一個迭代器,可以通過調用 next() 方法來獲取下一個生成的值。Generator函數中的所有yield語句都執行完畢后,done屬性為true,表示generator函數已經結束(這里的流程描述比較抽象,后面用實際案例來解釋會更好)。

GeneratorFunctions 是 Python 首先從 Coroutine 語言中的 coroutine() 概念演變而來,然后引入到 E6 標準中,希望用它來提高 JavaScript 中處理異步編程的能力。

Generator基本語法

GeneratorFunctions 使用 function*the 關鍵字定義,它可以包含多個yield表達式來控制函數執行的流程:

function* myGenerator() {
  yield 1;
  yield 2;
  yield 3;
}

調用Generator函數并不執行函數內部的代碼,而是返回一個迭代器對象,next()通過調用這個對象的方法來執行函數的代碼,并返回yield表達式返回的值:

const myGeneratorIterator = myGenerator();
console.log(myGeneratorIterator.next()); // print { value: 1, done: false }
console.log(myGeneratorIterator.next()); // print { value: 2, done: false }
console.log(myGeneratorIterator.next()); // print { value: 3, done: false }
console.log(myGeneratorIterator.next()); // print { value: undefined, done: true }

Generator函數執行過程中,當yieldan表達式時,函數的執行會被掛起,并將表達式的值返回給調用者。 

當next()方法時,函數將從中斷處繼續執行;我們可以在函數中指定返回一個最終返回值,該值將被包裝在包含要返回的屬性的完成對象中:

function* myGenerator() {
  console.log('Start');
  yield 1;
  console.log('Middle');
  yield 2;
  console.log('End');
  return 'Done';
}


const myGeneratorIterator = myGenerator();
console.log(myGeneratorIterator.next()); // print Start, { value: 1, done: false }
console.log(myGeneratorIterator.next()); // print Middle, { value: 2, done: false }
console.log(myGeneratorIterator.next()); // print End, { value: 'Done', done: true }

生成器的高級使用

yield*表達式

Yield* 允許 Generatorus 調用另一個 Generator 函數或函數內的可迭代對象。

當 Generatora 函數到達yield*表達式時,它會暫停執行并將執行轉移到另一個 Generator 函數或可迭代對象。 

執行權不會返回到原來的Generatorfunction。

function* foo() {
  yield 1;
  yield 2;
}


function* bar() {
  yield* foo();
  yield 3;
}


for (let value of bar()) {
  console.log(value); // print 1, 2, 3
}

在這個例子中,表達式inGenerator函數調用該函數并將其迭代結果依次返回給該函數。bar()yield* foo()foo()bar()

數據交互

在Generator函數中,可以使用yield表達式將數據返回給調用者,調用者next()可以通過Generator方法將數據傳遞給函數。 

這使得調用者和 Generator 函數之間能夠進行數據交互。

function* foo() {
  let x = yield;
  yield x * 2;
}


let gen = foo();
gen.next(); // start generator
gen.next(10); // pass 10,print 20

在這個例子中,foo()函數的next()在第一次調用該方法時會停在第一個yield語句處,等待外部傳入的數據。 

然后,當next()方法時將從外部傳入的數據作為yield表達式的值,然后向下執行,直到下一個yield表達式返回數據。

實際用例

異步編程

GeneratorFunctions 還可以用于實現異步編程。可以通過調用next()方法和關鍵字:yieldPromise來控制函數的執行狀態

function* myGenerator() {
  const result1 = yield new Promise((resolve) => setTimeout(() => resolve('first'), 1000));
  console.log(result1);
  const result2 = yield new Promise((resolve) => setTimeout(() => resolve('second'), 2000));
  console.log(result2);
  const result3 = yield new Promise((resolve) => setTimeout(() => resolve('third'), 3000));
  console.log(result3);
}


const generator = myGenerator();
const promise = generator.next().value;
promise.then((result) => generator.next(result).value)
  .then((result) => generator.next(result).value)
  .then((result) => generator.next(result).value);

看起來是不是和 async/awaitof 角色很相似,下面是兩種語法的一些比較:

優勢:

控制流程更靈活:可以使用 Generator 函數控制異步操作的執行順序,多個異步操作可以按順序執行,每個操作完成后執行下一個操作,控制流程更靈活。

Generator函數的狀態可以復用:Generator函數的狀態可以保存在對象中,需要的時候函數可以繼續執行,并且可以使用保存的狀態繼續異步操作。

更通用:GeneratorFunctions 可用于處理各種類型的異步操作,包括事件、回調、迭代器和 Promisemore 。

缺點:

更高的代碼復雜性:使用 Generator 函數可能會增加代碼的復雜性,因為需要額外的代碼和處理步驟。

可讀性差:對比async/await,Generator函數的語法和代碼結構都比較復雜,可讀性不如async/await。

控制異步進程

使用 Generatorfunctions 也非常方便。假設有一個需求場景API需要獲取,所有數據準備好后進行下一步。 

此時可以使用Generator函數讓這個異步控制流程更加清晰:

function* fetchAllData() {
  const data1 = yield fetch('api1');
  const data2 = yield fetch('api2');
  const data3 = yield fetch('api3');
  return [data1, data2, data3];
}


function run(generator) {
  const iterator = generator();


  function handle(iteratorResult) {
    if (iteratorResult.done) {
      return Promise.resolve(iteratorResult.value);
    }


    return Promise.resolve(iteratorResult.value)
      .then(res => handle(iterator.next(res)));
  }


  return handle(iterator.next());
}


run(fetchAllData).then(data => {
  // handle all data
  console.log(data);
});

處理大數據可以節省內存

在處理大數據集時,如果一次性將所有數據加載到內存中,會造成內存浪費和程序性能下降。 

Generator函數可以用來按需處理數據,將數據一一讀取并轉換,減少內存占用,提高程序性能。

function* dataGenerator() {
  let index = 0;
  while (true) {
    yield index++;
  }
}


function* processData(data, processFn) {
  for (let item of data) {
    yield processFn(item);
  }
}


const data = dataGenerator();


const processedData = processData(data, item => item * 2);


for (let i = 0; i < 500; i++) {
  console.log(processedData.next().value);
}

實現狀態機

GeneratorFunctions 也可用于實現狀態機。狀態機是由一組狀態和狀態之間的轉移規則組成的數學模型,可以用來描述系統的行為和狀態。 

在實際開發中,狀態機可以用來處理復雜的業務邏輯,比如表單驗證、工作流控制等。

使用Generator函數實現狀態機的過程如下:

定義狀態機的各種狀態,每個狀態對應一個 Generatorfunction 。

狀態之間的轉換是使用 Generatorfunction 的 statements.yield 實現的

調用Generator函數時,使用循環依次執行各個狀態,直到狀態機完成。

這是 Generator 實現的示例:

function* stateMachine() {
  let state = 'start';


  while (true) {
    switch (state) {
      case 'start':
        console.log('Enter start state');
        state = yield 'start';
        break;


      case 'middle':
        console.log('Enter middle state');
        state = yield 'middle';
        break;


      case 'end':
        console.log('Enter end state');
        state = yield 'end';
        break;
    }
  }
}


const sm = stateMachine();


console.log(sm.next().value); // Enter start state
console.log(sm.next('middle').value); // Enter middle state
console.log(sm.next('end').value); // Enter end state

最后

Generator與async/await相比,語法更加復雜,需要手動控制執行過程,使用起來相對麻煩。這也是我很少看到Generatorit被使用的原因之一。

這種語法實際上并不像看上去那樣簡潔易懂。 

但是在做一些復雜的控制流和狀態機處理的時候還是很有用的,Generator可以讓我們的流程更加清晰。

責任編輯:華軒 來源: web前端開發
相關推薦

2021-05-27 20:50:28

return生成器參數

2023-03-01 00:07:32

JavaScript迭代器生成器

2011-12-23 13:42:05

JavaScript

2024-02-19 00:00:00

Python?starmap函數

2023-12-13 15:28:32

Python工具數據

2011-03-22 09:49:25

J-Hi

2025-01-20 09:02:00

列表推導生成器表達式Python

2025-01-06 09:06:04

JavaScriptWeb 開發Generators

2021-06-06 16:31:57

PythonPython 3.7 編程語言

2017-09-06 09:26:03

Python生成器協程

2009-07-01 17:30:14

樣式生成器Visual Stud

2022-02-15 10:30:58

UUID

2024-01-25 10:23:22

對象存儲存儲數據

2009-07-01 17:35:04

樣式生成器Visual Stud

2015-08-25 11:07:58

2017-07-01 16:02:39

分布式ID生成器

2025-01-23 08:36:27

CSS開發工具

2010-09-07 16:31:17

SQL語句insert

2021-04-22 21:15:38

Generator函數生成器

2024-02-22 12:18:16

Python函數用法
點贊
收藏

51CTO技術棧公眾號

主站蜘蛛池模板: 秋霞a级毛片在线看 | 国产在线永久免费 | 日韩高清电影 | 成人国产精品久久久 | 色视频网站| www.天天操| 中文字幕人成乱码在线观看 | 亚洲欧美日韩电影 | 欧美 日韩精品 | 在线免费观看欧美 | 中文字幕人成人 | 久久精品欧美一区二区三区麻豆 | 天天草视频 | 综合久久久久久久 | 亚洲精品中文在线 | 亚洲小视频在线观看 | 精品蜜桃一区二区三区 | 亚洲精品久久久一区二区三区 | 久久精品久久久 | 精品国产一区二区在线 | 日韩在线观看网站 | 午夜国产羞羞视频免费网站 | 国产97在线看 | 久久久精品国产 | 国产91在线播放精品91 | 亚洲第一视频网站 | 午夜在线视频 | 久久成人国产精品 | 国产一区二区三区四区五区加勒比 | 亚洲成年在线 | 亚洲免费观看视频 | 亚洲视频一区在线观看 | 日韩精品成人 | 欧美偷偷操 | 欧美一级久久 | 国产精品视频网站 | 国产美女久久 | 中日韩av | 精品欧美二区 | 欧美日韩亚洲一区 | 日韩中文一区二区 |