生成器(generator)和Promise

316 阅读4分钟

生成器是一种特殊类型的函数。

我们正常从头到尾运行标准函数时候,最多只能生成一个值(return出一个值),但是生成器函数会在几次运行请求中暂停,因此每次运行都可能会生成一个值。

1、生成器函数

生成器函数能生成一组值得序列,但是每个值的生成是基于每次请求的,并且不是标准函数那样立即生成。必须显示的项生成器函数请求一个新的值,随后生成器要么响应出一个新值,要么告诉我们之后都不会再生成新值。

 function* fn() {            yield "1";            yield "2";  }  for(let val of fn()) {      console.log(val,'val')  }

如上,我们可以循环输出生成器函数的值

原因:可以简单理解为 调用生成器并不会执行生成器函数,相反,它会创建一个叫做迭代器的对象

1.1通过迭代器对象控制生成器

function* generatorFn() {            yield "xiaoming";            yield "xiaohong";            yield "xiaole";        }const myInterator = generatorFn(); // 调用生成器得到一个迭代器// 1、调用迭代器的next方法,向生成器请求一个新值 2、result1 为一个对象,其中包含着一个返回值和一个指示器百世之后是否还有新值生成const result1 = myInterator.next(); console.log(result1,'result1');
// {"value": "xiaoming","done": false}   result1

迭代器用于控制生成器的执行

调用迭代器对象的next方法后,生成器就开始执行代码,当执行到yeild的之后,会生成一个中间值,然后返回一个新对象(里面有value和done)

每当生成一个当前的值后,生成器会非阻塞的挂起执行,等待下一次的请求的到达

随后再次调用next

const result1 = myInterator.next(); 

此时会将生成器从挂起状态唤醒,继续从上次离开的位置继续执行代码,直到遇到另一个中间值yeild,然后返回一个新的对象

最后一次调用next时,生成的新对象的value为undefined,done为true

使用while循环来迭代生成器生成的值序列

原理:通过调用生成器的得到的迭代器,会暴露出一个next方法,next能让我们向生成器请求一个新值。next方法返回一个有value和done的对象,done为true时候表示之后不会再生成新值

function* generatorFn() {            yield "xiaoming";            yield "xiaohong";            yield "xiaole";        }        const myInterator = generatorFn();        let item;        while(!(item = myInterator.next()).done) {            console.log(item,'item')        }
// {value: 'xiaohong', done: false} 'item'
// {value: 'xiaole', done: false} 'item'

yeild后也可以调用另一个生成器

        function* generatorFn() {            yield "xiaoming";            yield *generatorFn2();            yield "xiaole";        }                function* generatorFn2() {            yield '2-xiaoming';            yield '2-xiaohong';            yield '2-xiaole';        }        const myInterator = generatorFn();        let item;        while(!(item = myInterator.next()).done) {            console.log(item,'item')        }

// 输出
{value: 'xiaoming', done: false} 'item'
{value: '2-xiaoming', done: false} 'item'
{value: '2-xiaohong', done: false} 'item'
{value: '2-xiaole', done: false} 'item'
{value: 'xiaole', done: false} 'item'

1.2与生成器交互

作为生成器函数参数发送值

function* generatorFn3(action) {  
const yieldVal1 = yield ('1' + action);            
console.log(yieldVal1,'yieldVal1');            
const yieldVal2 = yield ('2' + yieldVal1 + action);            
console.log(yieldVal2,'yieldVal2');        
}        
const myInterator3 = generatorFn3('向生成器函数传参');        
const res3 = myInterator3.next();        
console.log(res3,'res3');        
const res4 = myInterator3.next('next函数内传参');        
console.log(res4,'res4');        
const res5 = myInterator3.next();        
console.log(res5,'res5');

使用next方法向生成器发送值

next调用的传参是上一个yield表达式的返回值

抛出异常

每个迭代器除了又next方法还有throw方法

function* generatorFn4() {            try {                yield "xiaoxiao";                console.log('fail'); // 此处的错误将不会发生            }            catch(e) {                console.log(e,"抛出catch异常")            }        }        const res6 = generatorFn4();        res6.throw("异常抛出");

1.4生成器内部分析

工作过程:挂起开始---》执行---》挂起让渡---》完成

挂起开始:创建一个生成器后,任何代码都没有执行

执行:执行要么是刚开始,要么是从上次挂起的地方继续执行。时机:调用next并且done为false

挂起让渡:当生成器在执行过程中遇到一个yeild表达式时候,会创建一个包含返回值的新对象,随后再挂起执行;生成器在这个状态暂停并等待继续执行

完成:生成器执行期间,如果代码执行到return语句或者全部代码执行完毕

生成器是如何跟随执行环境上下文的

待补充。。。。

2、Promise

用于简单的处理异步任务

在promise钱,我们通常使用回调函数来处理异步任务,这样会存在三个较为明显的问题:
1、当执行长时间任务时候,发生异常,会错误丢失

2、回调地狱

3、执行很多的同步任务

promise对象用于作为异步任务结果的占位符,它代表一个我们暂时还没获取到但是在未来有希望获取的值(所以 promise会存在三种状态 pending rejected fulfilled)

promise的执行顺序

拒绝promise(显式和隐式)

链式调用promise(在链式调用中如何捕获错误)

Promise.all

Promise.race

生成器与Promise结合