生成器

<!DOCTYPE html>
<html>
    <head>
        <meta charset="utf-8">
        <title></title>
    </head>
    <body>
        <script>
            // yield关键字,可以让代码在其出现的地方暂停执行,它只能在生成器函数内部使用。
            // 第一次调用,函数里面 yield之前的代码不会执行,需要调next方法,yield之前的代码才会执行
            // 但是 yield之后的代码不会执行(yield语句会执行,yield 右边的会执行,yield x++,下面的不会而已),需要继续next方法才会执行yield之后的代码
            // next方法 返回一个对象 ,value属性,value属性的值是当前yield语句的结果
            // done:true/false,是否迭代结束,true已迭代结束,继续调next方法,value则返回undefined
            // false则表示未迭代结束,可以继续调用next()
            // next方法可以接收参数,第一个next传递参数并不会被接收,只有从第二个next开始传递的参数才会被接收
            // 如果一个生成器函数中使用return,我们需要得到return的值,
            // 这时候需要使用next方法返回的对象的value属性得到返回的值。
            // 生成器函数
            // 生成器函数的语法比较简单在普通函数声明的时候在函数名前面添加一个*即可,如下所示:
            
            // 场景:判断是否需要继续发请求,放done为true的时候停止
            // function *gen(){}


            // 当函数被调用时会返回一个返回值,但是生成器函数与普通函数的返回值有些区别。
            // 普通函数如果没有使用return返回时,接收到的是undefined,
            // 而生成器函数不管有没有return都返回一个对象,这个对象被称为迭代器,
            // 我们可以通过这个对象控制迭代器的执行。 通常, 使用迭代器的next方法, 让其继续执行。

            // let x = 0;

            // function* gen() {
            //  console.log(x);
            //  yield x++;
            // }
            // let itr = gen(); //函数的里代码console.log(x);不会执行
            // console.log(itr); //返回一个gen函数名对象
            // itr.next()//函数的里代码console.log(x)执行了
            // console.log(x);// yield x++; 也执行了 1
            //根据上面的结果我们可以知道,生成器函数在被调用时并不会开始执行代码,但是得到了一个对象,
            //我们让它继续执行函数内的代码,需要调用next方法。

            // 看看next方法输出什么
            let x = 0;

            function* gen() {
                console.log(x);
                yield x++;
                console.log("ssssss",x);
                return x;
            }
            let itr = gen();
            let res = itr.next();
            console.log(res); //{value: 1, done: true}
            //next方法也会返回一个对象,这个对象包含一个value属性,value属性的值是当前yield语句的结果。
            //则是yield后面 x++ 的结果;
            //还有one属性的值表示迭代器的完成状态,为true表明完成迭代,为false,表明没有完成迭代。
            // console.log(res.value);
            res = itr.next();
            console.log(res.value, res);
            res = itr.next();
            console.log(res);
            //如果一个生成器函数中使用return,我们需要得到return的值,
            //这时候需要使用next方法返回的对象的value属性得到返回的值。

            // next方法也可以接收一个值

            // let x = 0;
            // function *gen(){
            //  console.log(yield);
            //   x++;
            //  return x;
            // }
            // let itr = gen();
            // let res = itr.next(6);
            // console.log(res);
            // res = itr.next(7);
            // console.log(res);

            // 根据结果我们可以知道, 第一个next传递参数并不会被接收, 
            // 规范和所有兼容浏览器都会默默丢弃传递给第一个next() 的任何东西。 
            // 传值过去仍然不是一个好思路, 因为你创建了沉默的无效代码, 这会让人迷惑。 
            // 因此, 启动生成器时一定要用不带参数的next()。

            // 只有从第二个next开始传递的参数才会被接收, 由此, 我们可以总结, 
            // next传递的值被上一个yield接收, next与field相差一个间隔。

            // 那么为什么会产生这个差距呢?

            // 因为第一个next(…) 总是启动一个生成器, 并运行到第一个yield处。 
            // 不过, 是第二个next(…) 调用完成第一个被暂停的yield表达式, 第三个next(…) 调用完成第二个yield, 以此类推。

            // 以上就是生成器函数的基本使用, 那么生成器函数到底有什么用或者说能够应用在什么场景呢?

            // 生成器函数可以应用在异步任务中, 
            // 当一个异步任务没有返回值时我们可以让程序在此处暂停当有返回值时在调用next继续执行。
            
            // function run(gen) {
            //   var args = [].slice.call(arguments, 1), it;
            
            //   // 在当前上下文中初始化生成器
            //   it = gen.apply(this, args);
            
            //   // 返回一个promise用于生成器完成
            //   return Promise.resolve()
            //     .then(function handleNext(value) {
            //       // 对下一个yield出的值运行
            //       var next = it.next(value);
            
            //       return (function handleResult(next) {
            //         // 生成器运行完毕了吗?
            //         if (next.done) {
            //           return next.value;
            //         }
            //         // 否则继续运行
            //         else {
            //           return Promise.resolve(next.value)
            //             .then(
            //               // 成功就恢复异步循环,把决议的值发回生成器
            //               handleNext,
            //               // 如果value是被拒绝的promise,
            //               // 就把错误传回生成器进行出错处理
            //               function handleErr(err) {
            //                 return Promise.resolve(it.throw(err)).then(handleResult);
            //               }
            //             );
            //         }
            //       })(next);
            //     });
            // }

        </script>
    </body>
</html>
©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容