一.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命令