generator的返回值和next的參數

看了一篇關於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
// }
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章