1. 程式人生 > >es6學習之Generator函式,async函式

es6學習之Generator函式,async函式

一.Generator函式的語法

1.概念和語法

(1)概念

Generator是一個狀態機,內部封裝多個狀態 ;
Generator會返回一個遍歷器,呼叫Generator的next方法可以依次執行

(2)語法

(1) function後面跟著*號,呼叫函式不會立即執行Generator函式,只有呼叫next方法的時候才會執行. next方法在yield表示式處停止,next返回一個物件,當value是undefined,done是true的時候,就結束了.
(2) next方法可以傳入引數,也可以不傳入,傳入的引數當作上一個yield表示式的返回值 . 這個功能能夠在Generator函式執行的各個階段傳入不同的值,進而有不同的行為.
(3) 可以使用for…of迴圈,到返回done為true時結束,也就是return 的結果不會被for…of捕獲

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

var hw = helloWorldGenerator();
// 使用next方法
hw.next();      // {value: "hello", done: false}
hw.next();      // {value: "world", done: false}
hw.next();      // {value: "ending", done: true}
hw.next();      // {value: undefined, done: true
} hw.next(); // {value: undefined, done: true} // 使用for迴圈,上面的next方法不能和for...of一起使用,因為狀態已經執行過了便固定了 for (let value of hw) { console.log('value',value); } // value hello // value world

2.Generator的函式方法

(1)Generator.prototype.throw()

  • 每一個Generator返回的遍歷器物件都有一個throw方法,不同於全域性的throw方法,它能在Generator中宣告try…catch,在遍歷的時候呼叫遍歷物件的throw方法,被Generator內部捕獲,但是外部物件throw一次,內部一個catch只能一次
  • 對用遍歷器物件的throw方法,會預設執行一次next方法
var g = function* () {
  try {
    yield;
  } catch (e) {
    console.log('內部捕獲', e);
  }
};

var i = g();
i.next();

try {
  i.throw('a');
  i.throw('b');
} catch (e) {
  console.log('外部捕獲', e);
}
// 內部捕獲 a
// 外部捕獲 b

(2)Generator.prototype.return()

遍歷器物件上還有一個return的方法,可以結束遍歷,即使下面還沒有遍歷結束 . 返回的引數的value時return方法的引數(如無引數則value=undefined),done為true,
如果Generator內有finally結構,則return方法會被推遲到finally執行完畢後執行

function* numbers () {
  yield 1;
  try {
    yield 2;
    yield 3;
  } finally {
    yield 4;
    yield 5;
  }
  yield 6;
}
var g = numbers();
g.next() // { value: 1, done: false }
g.next() // { value: 2, done: false }
g.return(7) // { value: 4, done: false }
g.next() // { value: 5, done: false }
g.next() // { value: 7, done: true }

(3)yield*表示式

在一個Generator的函式內部呼叫另一個Generator函式,另一個函式返回的是一個遍歷器物件

function* bar() {
  yield 'x';
  yield* foo();
  yield 'y';
}

// 等同於
function* bar() {
  yield 'x';
  yield 'a';
  yield 'b';
  yield 'y';
}

// 等同於
function* bar() {
  yield 'x';
  for (let v of foo()) {
    yield v;
  }
  yield 'y';
}

for (let v of bar()){
  console.log(v);
}
// "x"
// "a"
// "b"
// "y"

二.async函式

1.概念和語法

(1)概念

asyn函式就是Generator函式的語法糖,等待await後面的函式完成之後在執行下面的語句 .
async函式返回Promise,

(2)語法

function fun1 () {
    setTimeout(()=>{
        console.log('fun1');
    },2000);
}


function fun2 () {
    setTimeout(()=>{
        console.log('fun2');
    },3000);
}

const asyncFun = async function () {
    let f1 = await fun1();
    let f2 = await fun2();
    console.log(f1);
    console.log(f2);
}

asyncFun();
// 2秒後列印fun1
// 3秒後列印fun2

// 返回Promise
async function f() {
  return 'hello world';
}
f().then(v => console.log(v))
// "hello world"

2.async的函式語法

  • 返回Promise
  • Promise狀態的變化是當內部的所有await執行完才會改變,除非遇到return或者錯誤
  • 所有的await命令最好都放在try…catch中,否則一個await的promise變為reject就會終端async中的所有await命令