深入解读 ES6 系列(四)

8.0 来自老曾es6的前言:

  • 哈喽小伙伴们,爱说‘废’话的Z又回来了,欢迎来到Super IT曾的博客时间,上一节说了字符串,面向对象以及json的知识,这一节我们继续我们知识的海洋,一起奋斗不秃头!不足的欢迎提问留言。
    在这里插入图片描述
    我发誓我真的没有P图😂,没想到这个系列被小编看上了,从发布这个系列起就都上热门了,怪害羞的,哈哈让人老脸一红的既视感,既然如此!我会认真把这个系列做完的,然后带你们搞项目搞框架!我们一起搞事情!那现在我们就开始吧!这一节是es6结局哦,下节就要说es789....的啦哈哈哈。
    在这里插入图片描述

9.0 Promise

  • 老曾英语教学开始,promise是什么,是承诺,我可是一言九鼎的人啊,别说四匹马,四十匹马都拉不回来我,那么解释起来promise就是这件事我肯定会做,至于多久做嘛~反正肯定会做的对吧!那么promise和我们es6有什么关系呢?我们先卖个关子。
  • 这里就要先提到两个东西了,相信有一定基础的小伙伴一定知道我想说啥,对就是异步和同步。
两步 特点1 特点2
异步 操作之间没啥关系,可同时进行多个操作 代码更复杂
同步 同时只能做一件事 代码简单

那么你肯定又想问异步和同步项目中怎么应用的?我拿它来干嘛?我打个比方:
在这里插入图片描述
这里的图片数据文字数据等等都不是写死的吧,都需要从后台去拿,如果你使用异步,这时候就好比这种代码,也叫回调地狱,这种好吓人哦,要是上百条数据上千条那怎么遭得住,不知道你们遭得住不,反正我是遭不住。

//callback-hell 回调地狱
getFileContent('a.json',data => {
    console.log("data",data)
    getFileContent(data.next, data2 =>{
        console.log('data2',data2)
        getFileContent(data2.next, data3 =>{
            console.log('data3',data3)
        })
    })
})

这个时候就要请出我们的Promise了,它的作用就是用来消除异步操作,它具体是怎么的呢?一句话概括:

  • 用同步的方式,书写异步的代码

9.1 Promise到底怎么用

  • 我们以一个ajax示例来看,你说你不知道ajax怎么办,没关系,你跟着看,以我对你的了解你看得懂哈哈,至少不影响代码阅读,跟着看了之后,回头自己个儿再看一下ajax教程你就完全懂了,废话暂时到这,先看目录结构:
    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述
  • 现在,问题来了,我要在index里面ajax请求这两个json文件,成功打印出里面json内容,失败则弹出失败,想想怎么做?提示一点,Promise.all的使用:
    在这里插入图片描述
<script src="https://cdn.bootcss.com/jquery/3.4.1/jquery.js"></script>
   	<script>
   		let p1 = new Promise((resolve, reject) =>{
   			//异步代码
   			$.ajax({
   				url: 'dataA.text',
   				dataType: 'json',
   				success(arr) {
   					resolve(arr)
   				},
   				error(err) {
   					reject(err)
   				}
   			})
   		})
   
   		let p2 = new Promise((resolve, reject) =>{
   			$.ajax({
   				url: 'dataB.text',
   				dataType: 'json',
   				success(arr) {
   					resolve(arr)
   				},
   				error(err) {
   					reject(err)
   				}
   			})
   		})
   
   		Promise.all([
   			p1,p2
   		]).then((arr) =>{
   			let [resA,resB] = arr
   			alert("all success")
   			console.log(resA,resB)
   		},(err) =>{
   			alert("fails")
   			console.log(err)
   		})
   	</script>

光看代码有没有理解一点呢,别急代码会继续优化,我们先来解析代码,使用箭头函数和解构赋值的地方都是我们前面博客说过的咯,忘记的童鞋就自己翻看一下老曾之前的博文啦,当然我也是贴心大暖男,放图来给你注释解析:

  • 有道翻译 resolve--解决了,reject--拒绝了
  • 那拿到我们这里就明明白白了,resolve成功,reject失败
    图一,对应请求成功失败的执行以及返回:
    在这里插入图片描述
  • Promise对应成功失败的执行以及返回,绿字对绿框,紫字对紫框,红字对红框,顺便一提,无论是请求或是什么,有失败的函数一定要执行养成良好的习惯,我之前就不爱写失败的返回,蜜汁自信有没有哈哈哈,就会导致有时候不知道错误原因。
    在这里插入图片描述
    这样我怕你还不知道p1,p2,我给你打印一下可好?😋毕竟自己的粉自己疼p1,p2,console的代码中间有个逗号哈,只不过被线遮住了,看图就发现是promise对象:
    在这里插入图片描述
    现在来简化代码,我说过,我是个懒人,虽说p1和p2直接ctrl c+ctrl v再改改一个字母代码就好了,但我都懒得复制粘贴,两大坨代码看着就emm那啥,我们一个函数封装一下嘛:
<script>
	function createPromise(url){
		return new Promise((resolve, reject) =>{
			$.ajax({
				url: url,
				dataType: 'json',
				success(arr) {
					resolve(arr)
				},
				error(err) {
					reject(err)
				}
			})

		})
	}
	let p1 = createPromise("dataA.text")
	let p2 = createPromise("dataB.text")
	Promise.all([
		p1,p2
	]).then((arr) =>{
		let [resA,resB] = arr
		alert("all success")
		console.log(resA,resB)
	},(err) =>{
		alert("fails")
		console.log(err)
	})
</script>

这样就清爽的多了有没有,当然这远远不够,你还能像到更优化的吗?不能的话就跟着来,看看代码打印出啥?

let p = $.ajax({url:'dataA.text',dataTape:'json'})
console.log(p)

在这里插入图片描述
发现没jQuery返回的本身就有promise对象,所以我们不用自己用p1,p2接收一个promise,现在直接用就好了:

<script>
	Promise.all([
		$.ajax({url:"dataA.text",dataType:'json'}),
		$.ajax({url:'dataB.text',dataTape:'json'})
	]).then((arr) =>{
		console.log("success",arr)
	},(err) =>{
		console.log('fail',err)
	})
</script>

这样是不是爽多了有没有!!!!
在这里插入图片描述

  • 这才是Promise的完美用法,Promise.all是必须全部成功才执行成功,更像‘与’有没有,这里我们提一下另外一个,Promise.race,这个的话意思就是那个来了就先执行哪个,有一个成功都会执行成功的函数。

10.0 generator

10.1 generator的基本功能

  • 这是个啥?英语不好不存在哇搜一搜,翻译过来就是生成器。那这个有啥用?通俗易懂的来对比一下。
  • 普通函数:一路到底 —— 高铁火车
  • generator函数:随叫随停 —— 出租车
    那么我们就来看看这个generator和普通函数有啥不同?瞅瞅看打印出来是啥?猜猜?说实话我最开始也不知道哈哈哈😄,这里提示一下yield翻译过来是放弃的意思,我们这里把他理解为暂时放弃。
<script>
	function *show(){
		alert('a');
		yield;
		alert('b')
	}
	show()
</script>

你是不是觉得会弹出一个a,没想到吧,啥也没有,控制台也不报错,这时候咋办呢?alert(show()),同时 console.log(show())一下,查看一下呢?
在这里插入图片描述
alert出来的倒没啥,就告诉你执行出来是个生成器对象,但是当我们看他里面的时候就会发现里面有一个next方法,这个就很重要了。
在这里插入图片描述
那我们就来 show().next();执行一下看看是个啥?
在这里插入图片描述
那如果既要显示a又要显示b呢?我们试试这样写:

	let obj = show()
	obj.next();
	obj.next();

在这里插入图片描述
这样a,b就都出来了,这里只放了b,所以next给人的感觉就是踹一步走一下的感觉对吧。那你要问老曾老曾这个generator的原理是怎么实现走走停停的呢?你猜我给你说不说哈哈,当然要说。

  • generator的基本原理在这里就是把原来的*show()函数划分为了两个小函数,当然你是看不见的,这里就相当于划分为了show1和show2,各自执行alert('a')和alert('b')。

10.2 细说yield

yield传参

  • 上一个小点我们刚说了,yield是暂时放弃的意思,同时也对Promise有了一个基本的了解,那来看看这段代码你能猜对执行结果嘛?
<script>
	function *show(){
		alert('a');
		let a = yield;
		alert('b');
		alert(a);
	}
	let gen = show();
	gen.next(12);
	gen.next(5);
</script>

在这里插入图片描述
在这里插入图片描述
注意重点来了!
在这里插入图片描述
5???有没有怀疑人生?哈哈我很懵逼啊表示,来来来我们来分析一下两个next分别执行的是*show的哪两段代码:

在这里插入图片描述
第一次next是不是应该是白框框的代码,碰到yield暂停了嘛,第二次next就是黄框框的代码。所以 gen.next(5);是给谁传递的值,看黄框框,是不是就是给 let a传递的值,这样不难理解吧。

  • 那你说如果想给上面白框框alert值怎么办?
function *show(num1,num2){
		alert(`${num1} ${num2}`)
		alert('a');

		let a = yield;

		alert('b');
		alert(a);
	}
	let gen = show(9,99);
	gen.next(12);
	gen.next(5);

在这里插入图片描述
这样就可以了嘛,所以也可以看出第一个next对于yield传参是废的,是没有用的好吧。

yield返回

*来来来,yield传参玩完了我们来说说返回,一样一样来猜猜代码执行结果是什么?

<script>
	function *show(){
		alert('a');
		yield 12;
		alert('b');
		return 55;
	}
	let gen = show();
	let res1 = gen.next();
	console.log(res1)
	let res2 = gen.next();
	console.log(res2)
</script>

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
相信机智的你至少已经看出来了一点,这里的done就是是否执行完毕,那按照之前白框框和黄框框的理解,返回value是12和55能理解吗?还不能理解的话我们就来继续看~

yield到底是个啥

  • 这里咱就不搞代码了,咱来搞一个接地气的伪代码,你来品品:
    在这里插入图片描述
    说白了就像是一个厨房的分工以yield隔开,各做各的事情,就这么简单,还不懂得小伙伴评论区留言哦~

10.3 generator的实例

  • 介绍完了generator也了解了它的基本使用,那我们不是说它也可以用来消除异步操作嘛?那具体是怎么做的呢?
  • 首先我们需要一个runner文件,我会把它放在github上,文章末尾有github链接点进去在es6的15的文件夹里就可以看到啦,没找到文件的可以私聊我😊。
    在这里插入图片描述
<script src="https://cdn.bootcss.com/jquery/3.4.1/jquery.js"></script>
<script src="runner.js"></script>
<script>
	runner(function *(){
		let data1 = yield $.ajax({url:'dataA.text',dataType:'json'})
		let data2 = yield $.ajax({url:'dataB.text',dataType:'json'})
		let data3 = yield $.ajax({url:'dataC.text',dataType:'json'})
		console.log(data1,data2,data3)
	})
</script>

对应的dataA,B,C就有了,这里要注意一点就是我们第一个$.ajax返回的promise返回给了谁,我们这里其实返回给了runner去处理然后yield暂停,处理完了后就会回到data1继续执行,完了第二个ajax就会给data2,依次data3。
在这里插入图片描述

11.0 异步操作总结

11.1回调

//回调
$.ajax({
  url: xxx,
  dataType: 'json'
  success(data1){
    $.ajax({
      url: xxx,
      dataType: 'json'
      success(data2){
        $.ajax({
          url: xxx,
          dataType: 'json'
          success(data3){
            //完事儿
          },
          error(){
            alert('错了');
          }
        });
      },
      error(){
        alert('错了');
      }
    });
  },
  error(){
    alert('错了');
  }
});

11.2 Promise

//Promise
Promise.all([
  $.ajax({url: xxx, dataType: 'json'}),
  $.ajax({url: xxx, dataType: 'json'}),
  $.ajax({url: xxx, dataType: 'json'})
]).then(results=>{
  //完事儿
}, err=>{
  alert('错了');
});

11.3 generator

//generator
runner(function *(){
  let data1=yield $.ajax({url: xxx, dataType: 'json'});
  let data2=yield $.ajax({url: xxx, dataType: 'json'});
  let data3=yield $.ajax({url: xxx, dataType: 'json'});
  //完事儿
});

11.4 Promise的缺点

  • 光看上面的11.2和11.3是不是感觉两个差别不大,确实,但是如果promise带逻辑,就比如一个用户登录了是vip怎么怎么样,不是VIP又怎么怎么样?这个时候我们的代码是什么样子的呢?
//带逻辑-Promise
Promise.all([
  $.ajax({url: 'getUserData', dataType: 'json'})
]).then(results=>{
  let userData=results[0];
  if(userData.type=='VIP'){
    Promise.all([
      $.ajax({url: 'getVIPItems', dataType: 'json'})
    ]).then(results=>{
      let items=results[0];
      //生成列表、显示...
    }, err=>{
      alert('错了');
    });
  }else{
    Promise.all([
      $.ajax({url: 'getItems', dataType: 'json'})
    ]).then(results=>{
      let items=results[0];
      //生成列表、显示...
    }, err=>{
      alert('错了');
    });
  }
}, err=>{
  alert('失败');
});

我的天一大堆,来看看普通回调,这个时候说实话我还不如用普通回调。

//带逻辑-普通回调
$.ajax({url: 'getUserData', dataType: 'json', success(userData){
  if(userData.type=='VIP'){
    $.ajax({url: 'getVIPItems', dataType: 'json', success(items){
      //生成列表、显示...
    }, error(err){
      alert('错了');
    }});
  }else{
    $.ajax({url: 'getItems', dataType: 'json', success(items){
      //生成列表、显示...
    }, error(err){
      alert('错了');
    }});
  }
}, error(err){
  alert('错了');
}});

普通回调都比Promise好对吧,但是有了generator,来看看它怎么写?

//带逻辑-generator
runner(function *(){
  let userData=yield $.ajax({url: 'getUserData', dataType: 'json'});
  if(userData.type=='VIP'){
    let items=yield $.ajax({url: 'getVIPItems', dataType: 'json'});
  }else{
    let items=yield $.ajax({url: 'getItems', dataType: 'json'});
  }
  //生成、...
});

这个时候是不是感觉他的优势一下子就显现出来了,就和我们平时的普通函数执行一样,简单粗暴。

好了到这里我们的ES6说的就差不多了!!!!!!!!四个系列终于说完。
在这里插入图片描述
———————————————————————分割线——————
都看到这里了,只能说明一点,咱俩真的真的真的很有缘分啊!不点个赞再走嘛,😊😀,顺手加个关注嘛,偷偷收藏我博文的小可爱我后台看得到的嘛,点个赞给老曾支持支持,不出意外接下来我一直都在哈哈哈,学知识写博客不着急,基础打好,项目直接上手6到飞起。

下节说ES7,及之后版本的内容

放上我的,主要博客博客园CSDNGitHubpipe

你好,朋友😀,都看到这里了,说明咱俩是真的有缘,要不留个评论或者点个赞再走😊?

留下你的脚步
你好,朋友😊,来都来了要不认识一下,我叫大曾,你呢?
Super ITZ © 2024 下次又来看看我哦,再见朋友😊
0 浏览   4 文章
Powered by B3log 开源Pipe • Theme Koma by Vanessa