看了一篇關於generator和async/await關係的文章,受益匪淺。
文章的主要內容是:await是generator的語法糖
// Generator
run(function*() {
const res1 = yield readFile(path.resolve(__dirname, '../data/a.json'), { encoding: 'utf8' });
console.log(res1);
const res2 = yield readFile(path.resolve(__dirname, '../data/b.json'), { encoding: 'utf8' });
console.log(res2);
});
// async/await
const readFile = async ()=>{
const res1 = await readFile(path.resolve(__dirname, '../data/a.json'), { encoding: 'utf8' });
console.log(res1);
const res2 = await readFile(path.resolve(__dirname, '../data/b.json'), { encoding: 'utf8' });
console.log(res2);
return 'done';
}
const res = readFile();
可以看到,async function 代替了 function*,await 代替了 yield,同時也無需自己手寫一個自動執行器 run 了
但是對於文章內代碼的一些細節有一些疑惑,因此寫下自己的一些猜想,待日後考證
function* another() {
yield '人月神話';
}
function* gen() {
yield* another(); // 移交執行權
const a = yield 'hello';
const b = yield a; // a='world' 是 next('world') 傳參賦值給了上一個 yidle 'hello' 的左值
yield b; // b=! 是 next('!') 傳參賦值給了上一個 yidle a 的左值
}
const g = gen();
g.next(); // {value: "人月神話", done: false}
g.next(); // {value: "hello", done: false}
g.next('world'); // {value: "world", done: false} 將 'world' 賦給上一條 yield 'hello' 的左值,即執行 a='world',
g.next('!'); // {value: "!", done: false} 將 '!' 賦給上一條 yield a 的左值,即執行 b='!',返回 b
g.next(); // {value: undefined, done: false}
猜想:
第一次g.next()
,執行完yield* another()
第二次g.next()
, 執行完yield 'hello'
,並將hello
作爲g.next()
的返回值。但沒有執行const a 的賦值
第三次g.next('world')
,將world賦值給上一條的a,並執行完yield a
,即yield world
,將world返回。此時const b還沒有賦值。
第四次g.next('!')
,將!賦值給上一條的b,並執行完yield b
,將!返回
證明:
const promisify = require('util').promisify;
const path = require('path');
const fs = require('fs');
const readFile = promisify(fs.readFile);
const gen = function*() {
const res1 = yield readFile(path.resolve(__dirname, '../data/a.json'), { encoding: 'utf8' });
console.log(res1);
const res2 = yield readFile(path.resolve(__dirname, '../data/b.json'), { encoding: 'utf8' });
console.log(res2);
};
const g = gen();
const g1 = g.next(); // 獲取第一個yield的返回值,此時函數內const res1未賦值
console.log('g1:', g1);
g1.value
.then(res1 => { // value的值傳給res1,此處是promise
console.log('res1:', res1);
const g2 = g.next(res1); // res1的值傳給函數內的const res1,並執行完第二個yield,返回結果給g2。中間又輸出了一次res1,
console.log('g2:', g2);
g2.value
.then(res2 => {
console.log('res2:', res2); //同上
g.next(res2);
})
.catch(err2 => {
console.log(err2);
});
})
.catch(err1 => {
console.log(err1);
});
// g1: { value: Promise { <pending> }, done: false }
// res1: {
// "a": 1
// }
// {
// "a": 1
// }
// g2: { value: Promise { <pending> }, done: false }
// res2: {
// "b": 2
// }
// {
// "b": 2
// }