JS高级—12—可迭代对象与迭代器;生成器函数与生成器;async与await;


 

 

 

 

 

一、迭代器

 

 

 

 

二、可迭代对象

2.1什么是可迭代对象

 

 

 

 

 

 

2.2可迭代对象的作用,

通过可迭代对象可以很方便的生成一个新的迭代器;

for of循环就是可迭代对象才有的;forof就是一个语法糖,本质上就是调用迭代器的next()方法;

  • 注意:new Set是,传入的参数也要是一个可迭代对象;
  • 注意:{}不是可迭代对象,但是为什么也可以用spread snbtax和解构赋值,因为在es9中ecma要求所有的浏览器引擎实现这个“特性”,即使{}不是可迭代对象也要实现这个功能;当然这个功能不用迭代器也很容易实现;总的来说,到目前为止{}仍然不是可迭代对象;

 

 

 

 

2.3自定义类的迭代

 

 

 

 2.4迭代器的中断

通过调用break等,会调用迭代器的return方法;

 

 

 

 

 

 

 

三、生成器

生成器就是一个生成器函数放回的变量,这个变量是特殊的迭代器;

 

function* foo() {
    console.log(111)
    yield bar();
    console.log(333)

}

function bar() {
    console.log(2222)
    return Promise.resolve('helloworld');
}

generator = foo();
generator.next()
console.log(444)
结果是1111 2222   4444  
所以说:yied和await一样的,也是会去执行后面跟着的函数里的代码的,比如这里就是执行了bar()里的222; 只是遇到了resolve后才会让出控制权,等promise变成fullfilled态后会继续拿到js线程的控制权;



yield bar() 和bar()
所以说:yield和单纯的promise.then()方法还是不一样的,.then()方法会把回调函数加入到微任务队列,然后继续执行本函数下面的代码,但如果是yield,则不仅.then()方法会把回调函数加入到微任务队列,yield地下的代码也无法执行也应该被加入到微任务队列了;
至于原因,那可能就是ecma的规范如此定义的;

 

 四、生成器函数

4.1概念

调用生成器函数会返回一个生成器,

调用生成器的next方法,可以控制函数执行到下一个yield,并且yield后面跟的value会作为生成器的next方法返回值,格式为{value:'yield后面跟着value',    done: false};

 

4.2生成器next方法提供参数

我们给生成器的next()方法传递一个参数,在生成器函数中,可以痛哟const n= yield initial 接受,n就是我们传递的参数;

 

 

 4.3生成器return方法

 

 

 4.4生成器throw方法

如果有try catch,那么捕获到异常后后续的代码可以继续运行;

如果没有,那么就是直接抛出异常了,程序终止即js线程终止了;

 

 

注意第二个有问题,在catch中也可以继续放置yield; 

 

 

 

 

 

五、生成器替代迭代器

5.1概念

因为生成器函数会自动返回一个生成器,又因为生成器就是一种特殊的迭代器,所以我们可以使用生成器替代迭代器,使用生成器函数自动帮助我们生成生成器;

 

加了一个星号*,表示这个函数是生成器函数,生成器函数一定会返回生成器,可以调用生成器的next方法;

加了一个async,表示这个函数是异步函数,异步函数一定会返回一个promise(这个promise的状态依据异步函数是返回基本数值还是新的promise还是thenable接口而定),可以调用promise的then方法;

 

 

yield* 表示的意思是后面必须跟一个可迭代对象,然后它会不停的把可迭代对象的元素遍历出来;

这是一个语法糖,我们可以不用写这种代码了

for (  item  of arr){
  yield item
}

等价于

yield* arr

 

 

 

 

5.2自定义类的可迭代对象

 

 

5.3promise的异步解方案

第一种:回调地狱

第二种:链式调用

第三种:是最好的,asyncawait其实就是第三种的语法糖;

 

 

 

 

// request.js
function requestData(url) {
  // 异步请求的代码会被放入到executor中
  return new Promise((resolve, reject) => {
    // 模拟网络请求
    setTimeout(() => {
      // 拿到请求的结果
      resolve(url)
    }, 2000);
  })
}

// 需求: 
// 1> url: why -> res: why
// 2> url: res + "aaa" -> res: whyaaa
// 3> url: res + "bbb" => res: whyaaabbb

// 1.第一种方案: 多次回调
// 回调地狱
// requestData("why").then(res => {
//   requestData(res + "aaa").then(res => {
//     requestData(res + "bbb").then(res => {
//       console.log(res)
//     })
//   })
// })


// 2.第二种方案: Promise中then的返回值来解决
// requestData("why").then(res => {
//   return requestData(res + "aaa")
// }).then(res => {
//   return requestData(res + "bbb")
// }).then(res => {
//   console.log(res)
// })

// 3.第三种方案: Promise + generator实现
function* getData() {
  const res1 = yield requestData("why")
  const res2 = yield requestData(res1 + "aaa")
  const res3 = yield requestData(res2 + "bbb")
  const res4 = yield requestData(res3 + "ccc")
  console.log(res4)
}

// function* getDepartment() {
//   const user = yield requestData("id")
//   const department = yield requestData(user.departmentId)
// }

// 3.1> 手动执行生成器函数
const generator = getData()
generator.next().value.then(res => {
  generator.next(res).value.then(res => {
    generator.next(res).value.then(res => {
      generator.next(res)
    })
  })
})

// 3.2> 自己封装了一个自动执行的函数   !!当你不知道要执行多少次的时候,用递归;
// function execGenerator(genFn) {
//   const generator = genFn()
//   function exec(res) {
//     const result = generator.next(res)
//     if (result.done) {
//       return result.value
//     }
//     result.value.then(res => {
//       exec(res)
//     })
//   }
//   exec()
// }

// execGenerator(getData)
// execGenerator(getDepartment)

// 3.3> 第三方包co,就是我们写的自动执行函数,npm install安装后可以直接使用;
// TJ: co/n(nvm)/commander(coderwhy/vue cli)/express/koa(egg)
// const co = require('co')
// co(getData)

// 4.第四种方案: async/await async function getData() { const res1 = await requestData("why") const res2 = await requestData(res1 + "aaa") const res3 = await requestData(res2 + "bbb") const res4 = await requestData(res3 + "ccc") console.log(res4) } getData()

 

 

 

六、async和await

一个函数加了个async表示,这个函数是异步函数,函数体里会有异步操作。那么异步函数的执行流程是什么样的?

6.1概念

await后面要跟一个  返回promise的表达式

 

 

6.2异步函数的执行流程

咩有await时和普通函数一样,都是同步执行;

 

 

6.3await关键字

 

posted @ 2022-05-21 20:41  Eric-Shen  阅读(268)  评论(0编辑  收藏  举报