[完结篇] - 理解异步之美 --- promise与async await (三)

天下没有不散的宴席

**这个系列到这里应该就是最后一节了,**前两章着重讲了promise,为何着重讲promise呢?由于在用法上promise要比async await难一些,并且promise自己又不是一个语法糖。没有掌握的时候用起来就会有不少顾虑,async await却没有这种顾虑,用法简单、语义清晰。javascript

基础预热:你好,JavaScript异步编程---- 理解JavaScript异步的美妙前端

理解异步之美:Promise与async await(一)vue

理解异步之美:Promise 与 async await(二)java

下面就要开始学习async await了面试

不讲讲迭代器模式总以为怪怪的

对于java语言来讲,迭代器是一个很基本的模式,list与set结构都内置了迭代器。ajax

可是javascript并无这种结果(ps:ES6提供了set,并且也能够实现迭代器),可是咱们对这种模式实用的并非特别多。 迭代器模式是指提供一种方法顺序访问一个聚合对象中的各个元素,而又不须要暴露该对象的内部表示。编程

so:迭代器就是在不暴露对象的内部表示的状况下,可以遍历整个元素promise

核心嘛就是:不暴露内部,能够遍历内部异步

下面咱们就来实现一个简单的迭代器async

// 在数据获取的时候没有选择深拷贝内容,
// 对于引用类型进行处理会有问题
// 这里只是演示简化了一点
function Iterdtor(arr){
	let data = [];
    if(!Array.isArray(arr)){
        data = [arr];
    }else{
        data = arr;
    }
    let length = data.length;
    let index = 0;
    // 迭代器的核心next
    // 当调用next的时候会开始输出内部对象的下一项
    this.next = function(){
    	let result = {};
    	result.value = data[index];
    	result.done = index === length-1? true : false;
    	if(index !== length){
            index++;
            return result;
    	}
    	// 当内容已经没有了的时候返回一个字符串提示
    	return 'data is all done'
    };
}
let arr = [1,2,3,4,5,6];
// 生成一个迭代器对象。
let iterdtor = new Iterdtor(arr);
iterdtor.next()
iterdtor.next()
复制代码

这就符合迭代器模式的特色,并无暴露内部的对象, 经过next的方法能够遍历内部对象。

说到如今不少人应该还没理解为何要说迭代器。

Generator函数执行后会返回一个迭代器

async函数是Generator的语法糖

这两个理由是否是一会儿就说明写迭代器是颇有用处的。

书写一个简单的Generator函数

function *Iterdtor(){
	console.log(1);
	yield '123';
	console.log(2);
	yield '234';
	console.log(3);
	return '345'
}
let iterator = Iterdtor();
复制代码

咱们执行了一下Generator函数返回一个迭代器。经过next方法,能够阻塞性的去执行Generator的代码。

一说到阻塞你们就想到同步等待阻塞线程致使页面十分卡顿,明明不是一件很好的事情,为何要用这种东西呢?

下面咱们就聊聊这种阻塞性的方式有什么好处呢?

在Generator函数中,迭代器调用next函数后,会一直执行到有yield标示的位置中止。等待next的下一次调用后,代码会继续执行到下个yield表示。没有yield的话就一执行到最后return的位置(没有return就会一直执行完全部的代码,这句话好像是个废话)。

代码就像挤牙膏同样,挤一点出一点挤一点出一点,最后没有卡顿的地方,一口气挤到底。

因此说若是实用Generator的方式来处理异步的请求会是怎样的一种感受。

// 伪代码
let ajaxSign = false;
function *ajaxGetSomething(){
    ajaxSomethingOne().then(res=>{ajaxSign = true})
    yield
    ajaxSign = false;
    ajaxSomethingSecond().then(res=>{ajaxSign = true})
}
let iterator = ajaxGetSomething();
iterator.next();
while(ajaxSign){
    iterator.next()
}
复制代码

若是以这种方式来实现异步的请求会怎样,

1:有一个标志表明ajax请求完成。

2:当标志为true时表明ajax执行完成,能够进行下一个事件了。

3:当标志为false代码ajax还未执行完成,继续阻塞下面的代码。

4:当第一个标志为true时,执行next(),而后发现到下一个yield之间有异步的代码,将标志设置为false,开始执行ajax的事情,阻塞着后面的内容。

5:当ajax完成后把标志设置为true,开始2的内容作的事情不断执行着直到整个迭代器完成。

粗俗的while循环实现next的调用是不可取的(毕竟伪代码)

这种方式让咱们体会到另外一种处理异步的方式,就是阻塞时的去执行多个串行的异步任务,这样能够感觉同步的写法去书写异步的代码,也就不会在不合适的时间去拿去异步的产生的数据,你阻塞着线程,你不等他执行完,你取值的操做也作不了呀。

如何实用async await

说到这里如何使用他们就比较清晰明了了吧

async function ajaxGetData(){
    xxxx
    dosomething()
    await ajaxGetDataFirst()
    dosomething()
    await ajaxGetDataSecond()
    dosomething()
    xxx
}
ajaxGetData()
复制代码

这个时候咱们使用async函数来处理异步效果就很清晰了,

咱们作了一些事情,而后到一个异步的ajax请求后,等待ajaxGetDataFirst这个异步的事件执行完毕后,开始继续作一些事情,到了第二个ajax异步请求ajaxGetDataSecond(),开始执行阻塞住函数的执行,等待异步事件执行完毕后就继续作下面的事情。用await关键字的时候就是在告诉下面的代码,这块你得给我等着,wait我执行完了才能轮到你 understand?总之await吊极了。

await在何时能够用? 只有在async函数体内部使用,并且这个做用范围是不能够继承下去的。

在promise中怎么使用async函数

new Promsie(async (resolve,reject)=>{
     await xxx
 })
 // 这样的async才能使await有效果,书写在promise以外的话await就会像上面同样报错
复制代码

await 能够接收一个同步的事情吗?继续执行下去不阻塞

async函数的返回值是什么? async函数的返回值是一个promise对象,

???? what 返回了一个promise对象。这有啥用呢?请听下面分析 这就表明着你在执行完全部的异步请求后还能够继续将你须要的结果用return的方式保存在一个promise对象中。promise的用处是什么?他好像能够存储一个值在指定状况下触发一个回调函数(这个不理解的能够看一下上一篇内容哈)因此这能够帮助咱们把内部的异步请求的数据抛出到函数外部来。

下面的使用场景:

在使用场景中,咱们有的时候须要异步的一个结果,好比ajax请求的结果,这个时候咱们但愿获得这个异步的结果怎么办? 这个时候await能够帮助我,在执行完异步的操做的时候拿到结果,在拿到结果后顺序执行下去。直到return的时候把这个结果 return出去,

如下两种写法咱们是均可以使用的

async function fn(){
	let result = await new Promise((resolve,reject)=>{
		setTimeout(()=>{
            resolve(100)
		},10000)
	}).then(res=>{
			return res
		})
	return result
}
let a = fn()
复制代码
async function fn(){
	let result = await new Promise((resolve,reject)=>{
		setTimeout(()=>{
            resolve(100)
		},10000)
	})
	return result
}
let a = fn()
复制代码

这两种方式均可以等待异步的promise执行完成以后再赋值给result,这个时候,咱们返回的a就是一个pending状态的promise对象,上一章节咱们讲过了promise的基本原理,后面的操做我就很少提了,因此获得你想要的内容的promsie你就会操做了。

这个时候咱们async内的异步操做的结果天然而然的能够抛出到函数外部来使用,能够解决不少的业务的封装问题了。

async 与 Generator的区别

async 与Generator的区别是什么?

async是Generator的语法糖,Generator是能够用来实现async的,用Generator来实现async的核心就是实现这种不需next调用自执行的内容,这是我之后要进行学习的(目前时间不是很充裕,打算学好以后出一个特别篇好好实现如下async)

尾声咯

这一节内容并无讲不少async的内容,反而是先讲了迭代器,再讲了Generator,最后对async的使用简单介绍了一下,这是我在学习async时的顺序,async用起来容易、同步的写法也比较熟悉,but!!!易用的东西每每表明着方法内部蕴含不少你不知道的东西, 这才是咱们要挖掘的AV8D!!!!

总结一下

异步的事情咱们理解了,异步程序执行的过程,了解了event table,任务队列,宏任务微任务的执行前后条件。了解了异步promise的用法,promise的实现机制、async的用法,以及衍生出来的迭代器知识。

这一段时间和边学习边产出文章,有一种被你们鞭策的感受,哈哈哈哈哈。鞭策这个词有点怪怪的,这个过程当中我发现学习不能只有兴趣,兴趣能够帮你研究你喜欢的内容时有无限的动力,上了发条同样,在你低谷、没有兴趣的时候还须要鞭策来帮你去学习新的不擅长的知识,

之前异步是我掌握最差的部分,在这一个阶段的学习我收获不少不知道身为读者的你收获了多少呢? 只有你本身知道了

有结束也有开始

异步的美妙咱们就算是先告一段落。

下面的一个巨大的系列章节,我将会对vuer-router源码进行一个系统的学习,而且随着学习之中产出文档哟,算是继续鞭策和与你们一块学习。 仍是那个熟悉的结束语:每个前端coder(boy and girl)大家永远不是一我的在战斗~

我是一个应届生,最近和朋友们维护了一个公众号,内容是咱们在从应届生过渡到开发这一路所踩过的坑,已经咱们一步步学习的记录,若是感兴趣的朋友能够关注一下,一同加油~

我的公众号:IT面试填坑小分队
相关文章
相关标签/搜索