es6-async await 手写 前端进阶必备
虽然上次的表白计划不了了之了,但我依然每天对她嘘寒问暖,我总相信,只要我对她好,总有一天我会感动她的。我也开始了所谓的舔狗之路......
一次和她的聊天中知道她喜欢吃大后街的一家早餐,但每天都起不来。然后我提出帮她带早餐,起初她还觉得有点不好意思稍稍有拒绝的意思,后来在我一系列劝说下答应了,她答应的那一刻,我高兴的像个孩子,那是我们除同学之外的第一个交集,也给我无限的遐想和期望。
大后街还是有点远的,为了防止面条软了,我也特意去买了辆自行车,还记得第一次买早餐的时候,我给自己定了6点的闹钟,兴奋、期待、紧张的我4点多就醒了,然后就毫无睡意了,脑子里一直在想等会应该和她说些啥,在哪里等她下来.....
给她带早餐的第六天,她说她来那个了,下来不了了,她的室友帮她下来拿的,那时候的我对这方面真的不懂,我们那的人感觉都太保守了,对这种东西比较隐晦,于是我百度了一下,然后叮嘱她多喝红糖水,多休息之类的话。聊着聊着我就怀着好奇问了一下她:“这大姨妈一个月来几次哇?”。这句话也让我成为了大学班上四年的笑话,至今还被他们提起.....
前言提示
各位掘友们,此篇文章需要从头认真往下阅读,不然无法理解下文我通过生成器*函数和yield实现的async awit。认真阅读包你搞透async 生成器 迭代器这些知识点。
整理知识点不易,如果大家学到了,帮我点赞关注,后续我会继续写进阶知识点。
迭代器、生成器、async
迭代器:迭代器是一种特殊对象,它具有一些专门为迭代过程设计的专有接口,所有的迭代器对象都有一个next()方法,每次调用都返回一个结果对象。结果对象有两个属性:一个是value,表示下一个将要返回的值;另一个是done,它是一个布尔类型的值,当没有更多可返回数据时返回true。迭代器还会保存一个内部指针,用来指向当前集合中值的位置,每调用一次next()方法,都会返回下一个可用的值
如何区分是否能迭代
let arr=[1,2,3]let str='123'let obj={a:1,b:2}for(var i of arr){console.log('数组',i)}for(var i of str){console.log('字符串',i)}for(var i of obj){console.log('对象',i)}
打印结果如下图

说明:对象是不可迭代的
可以从原型去看一个类型是否支持迭代,以字符串为例
展开字符串的原型,会发现它存在Symbol(Symbol.iterator)这个属性,说明它是可以迭代的。
把这个属性用起来,再结合迭代器的描述,你或许能进一步理解迭代器。
以 let str1='舔狗的泪' 为例

手动实现一个迭代器效果 以对象为例
var obj = {a: 1,b: 2,c: 3,[Symbol.iterator]() {var index = 0;let map = new Map([["a", 1],["b", 2],["c", 3],]);return {next() {let mapEntries = [...map.entries()];//将它还原成二维数组if (index < map.size) {return {value: mapEntries[index++],done: false,};} else {return { value: undefined, done: true };}},};},};let iter=obj[Symbol.iterator]()
测试下,同时会发现这个对象是能支持for of 的


遍历和迭代的区别
迭代:从目标源依次逐个抽取的方式来提取数据。目标源是有序,连续
遍历:只要能够循环数据,并不需要有序。
因为对象循环不是有序的,所有它无法迭代,但是Map是可以支持迭代的。
生成器
函数前带 * 表示生成器 用yield去产出它的值
function * test(){yield 1yield 2yield 3}var iter=test()iter.next()//输出 {value:1,done:false}
iter也是可以通过for of循环,这里不演示了
注意:每次调用next,他都会走到一个yield,下面代码不会打印log
function * test(){console.log('舔狗的泪')yield 1yield 2yield 3}var iter=test()//要调用iter.next()才会走console.log
将生成器的yield 换成return 看看区别:

基于yield去改造刚才让对象能够迭代的方法
var obj = {a: 1,b: 2,c: 3,[Symbol.iterator]:function * () {var index = 0;let map = new Map([['a', 1],['b', 2],['c', 3]]);let mapEntries = [...map.entries()]; //将它还原成二维数组while(indexyield mapEntries[index++]}}};let iter = obj[Symbol.iterator]();
对next方法传参,看看yield丑陋的一面,async前世
function* test() {let value1 = yield 1;console.log('value1',value1);let value2 = yield 2;console.log('value2',value2);let value3 = yield 3;console.log('value3',value3);}var iter=test()iter.next('one')iter.next('two')iter.next('three')iter.next('')
结果分析:next里面的值会赋给上一次yield 的值 。
站在开发者角度更期望 value1 打印的值就是1。async await它来了
async await基本操作
async await常见用法:let x=await 异步请求
看看它的其他用法,直接看图说话:
function b() {return new Promise(resolve => {setTimeout(() => resolve(1), 1000);});}async function a() {let value = await b();console.log(value);}a();//1秒后打印1
function b(){return 1}async function a() {let value = await b();console.log(value);}a();//打印1
function b() {let c = 1;}async function a() {let a = await b();console.log(a);}a();//打印undefined
基于* yield实现一个async
以下面例子去实现
let num=1//b函数只为模拟一个axiosfunction b() {return new Promise(resolve => {setTimeout(() => resolve(num++), 1000);});}async function a() {let value1 = await b();let value2 = await b();let value3 = await b();console.log(value1,value2,value3);return value3}let promise =a();//3秒后打印 1,2,3
基于生成器 递归实现,需要先看上面的对next方法传参,你才能明白下图let num = 1;function b() {return new Promise(resolve => {setTimeout(() => resolve(num++), 1000);});}function* a() {let value1 = yield b();let value2 = yield b();let value3 = yield b();console.log(value1, value2, value3);return value3}function Co(iter) {//因为async方法内部包裹的就是Promise,所以这里也return一个Promisereturn new Promise((resolve, reject) => {let next = function (data) {let { value, done } = iter.next(data);if (done) {resolve(data);} else {//兼容b函数是一个非异步操作value instanceof Promise?value.then(val => {next(val);}, reject):next(value);}};next();});}let promise = Co(a());
个人理解及总结
迭代器:它的原型上面存在Symbol(Symbol.iterator),它可以被for of 循环
生成器:* 配合yield 的一个函数
如果你搞懂了生成器函数,基于它实现async await就变得很容易了。
目前把es6里面的class Map Set Promise底层实现都写完了
源自:https://juejin.cn/post/7029100142208745503
声明:文章著作权归作者所有,如有侵权,请联系小编删除。
