function *genFunc(x){ console.log(`before yield x + 1 x = ${x}`) var y = yield (x + 1) console.log(`before yield y + 1 x = ${x} y = ${y}`) var z = yield (y + 1) console.log(`before yield z + 1 x = ${x} y = ${y} z = ${z}`) var i = yield (z + 1) console.log(`before return x = ${x} y = ${y} z = ${z} i = ${i}`) return i }
const a = genFunc(5) // 第一次传递参数是无效的,传递的参数表示上一个yield表达式的返回值!value = x + 1 console.log(a.next(4)) // before yield x + 1 x = 5 { value: 6, done: false } // 传入 3 y = 3,value = y + 1 = 4 console.log(a.next(3)) // before yield y + 1 x = 5 y = 3 { value: 4, done: false } // 传入 2 z = 2, value = z + 1 = 2 console.log(a.next(2)) // before yield z + 1 x = 5 y = 3 z = 2 { value: 3, done: false } // 传入 1 i = 1, value = i + 1 = 1 console.log(a.next(1)) // before return x = 5 y = 3 z = 2 i = 1 { value: 1, done: true }
const b = genFunc() console.log(b.next()) // before yield x + 1 x = undefined { value: NaN, done: false } console.log(b.next()) // before yield y + 1 x = undefined y = undefined { value: NaN, done: false } console.log(b.next()) // before yield z + 1 x = undefined y = undefined z = undefined { value: NaN, done: false } console.log(b.next()) // before return x = undefined y = undefined z = undefined i = undefined { value: undefined, done: true }
模拟过程(极简)
1 2 3 4 5 6 7 8 9 10 11 12
function *genFunc(){ console.log('before yield 1') var a = yield1 console.log(`before yield 2 a = ${a}`) var b = yield (a + 1) console.log(`before return b = ${b}`) return a + b } const gen = genFunc() console.log(gen.next()) // before yield 1 { value: 1, done: false } console.log(gen.next(2)) // before yield 2 a = 2 { value: 3, done: false } console.log(gen.next(3)) // before return b = 3 { value: 5, done: true }
function *genFunc(){ yield1 yield2 return3 } var gen = genFunc() var res = gen.next() while (!res.done){ console.log(res.value) res = gen.next() } console.log(res.value)
functionco(genF){ var gen = genF() functionnext(){ var args = Array.prototype.slice.call(arguments) var res = gen.next.apply(gen, args) if(res.done) return res.value // 传入 next 作为 callback, 这就是实现 co 自动执行的关键! // next 被触发时,异步任务已经得到结果,并执行下一个 gen.next ! // 这也是为什么 co 是需要后面跟 Thunk 函数的原因! res.value(next) } next() } function* genF(){ var i = yieldthunkAsync(1) // 这里进行传参,执行后是需要传入 callback 才开始执行异步 var j = yieldthunkAsync(2) console.log(i, j) return i + j } co(genF)