携手创作,共同成长!这是我参与「掘金日新计划 · 8 月更文挑战」的第20天,点击查看活动详情
来源
Generator 函数是ES6 提供的一种异步编程解决方案
Generator与协程
Generator与协程
协程有点像函数,又有点像线程,它的运行流程大致如下。
第一步,协程A开始执行
第二部,协程A执行到一半,进入暂停,执行权转移到协程B
第三步,(过了一段时间)协程B交换执行权
最后,协程A恢复执行
协程适合用于多任务运行环境,它与普通的线程很相似,都有自己的执行上下文,可以分享全局变量。他们的不同之处在于,线程可以在同一时间内,多个线程同时执行互不打扰,而携程同一时间只能运行有一个,其他协程都是处于暂停状态。
由于JavaScript是单线程,只能保持一个调用栈,引入协程之后,每一个任务可以保持自己的调用栈,这样就可以再抛出错误的时候找到原始的调用栈,不至于像异步操作的回调函数那样,一旦出错,原始的调用栈早就结束了。
Generator 函数是 ES6 对协程的实现,但属于不完全实现。Generator函数被称为“半协程”(semi-coroutine),意思是只有 Generator 函数的调用者,才能将程序的执行权还给 Generator函数。如果是完全执行的协程,任何函数都可以让暂停的协程继续执行。
generator的创建
最简单的generator,function关键字与函数名之间加一个星号,就从普通函数升级为generator函数了
function* hello() {
console.log('end')
}
var h=hello()
console.log(h.next()) // { value: undefined, done: true }
没有yield的generator,作用可以认为就是一个普通function能做的事, 调用hello(),得到一个迭代器对象,调用迭代器对象next(),返回迭代器元素的包裹值 value就是迭代器中保存的值,done就是迭代器是否完成
generator函数调用时,函数并不会立即执行,但是参数会被接收,返回一个对象,调用这个对象next方法,会执行函数里函数开始的地方到第一yield语句为止,就是记录一个指针指向了yield后面的值,所有会返回一个当前指针的位置和状态{value:1,done:false},value就是yield后面的值,done表示是否return了,没有return就是false,return后就true
特点1
第一个next是最不受尊重的,因为它传的参数会被忽略,没人接收,这也是合理的,因为next参数会作为上个一个yield的返回值,因为第一段代码段没有yield,所以会被忽略。
function* hello(h) {
console.log(h);
var x = 1
var y = yield x++;
console.log(y);
var n = yield x++
console.log(n)
}
var h = hello("第一")
h.next('忽略')
当遇到return 就代表迭代结束了,如果在for of 里,done true 的值不会输入。人为的调用next,除了return 那句能得到value是return后面的value,后面再调用就是undefined
function* hello(h) {
console.log(h);
var x = 1
var y = yield x++;
console.log(y);
var n = yield x++
console.log(n)
return 'end 了'
}
var h = hello("第一")
h.next('忽略') // 第一
console.log(h.next('第二')) //第二 { value: 2, done: false }
console.log(h.next('第三')) //第三 { value: 'end 了', done: true }
console.log(h.next('第四')) //{ value: undefined, done: true }
for of ,就是遍历h.next(),每次把i赋值给h.next,如果next返回的done为true,就结束遍历
function* hello(h) {
console.log(h);
var x = 1
var y = yield x++;
console.log("y",x);
var n = yield x++
console.log("n",x)
return 'end 了'
}
var h = hello("第一")
for(let i of h){
console.log(i)
}