深入解读ES6系列(四)
来自老曾es6的前言:
- 哈喽小伙伴们,爱说‘废’话的Z又回来了,欢迎来到Super IT曾的博客时间,上一节说了字符串,面向对象以及json的知识,这一节我们继续我们知识的海洋,一起奋斗不秃头!不足的欢迎提问留言。
我发誓我真的没有P图,没想到这个系列被小编看上了,从发布这个系列起就都上热门了,怪害羞的,哈哈让人老脸一红的既视感,既然如此!我会认真把这个系列做完的,然后带你们搞项目搞框架!我们一起搞事情!那现在我们就开始吧!这一节是es6结局哦,下节就要说es789....的啦哈哈哈。
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了,它的作用就是用来消除异步操作,它具体是怎么的呢?一句话概括:
- 用同步的方式,书写异步的代码
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,这个的话意思就是那个来了就先执行哪个,有一个成功都会执行成功的函数。
generator
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')。
细说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隔开,各做各的事情,就这么简单,还不懂得小伙伴评论区留言哦~
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。
异步操作总结
回调
//回调
$.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('错了');
}
});
Promise
//Promise
Promise.all([
$.ajax({url: xxx, dataType: 'json'}),
$.ajax({url: xxx, dataType: 'json'}),
$.ajax({url: xxx, dataType: 'json'})
]).then(results=>{
//完事儿
}, err=>{
alert('错了');
});
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'});
//完事儿
});
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,及之后版本的内容
深入解读ES6系列(四)的更多相关文章
- 深入解读ES6系列(三)
ES6字符串 哈喽小伙伴们,爱说'废'话的Z又回来了,欢迎来到Super IT曾的博客时间,上一节说了函数,解构赋值和数组的五大将,这一节我们继续我们知识的海洋,一起奋斗不秃头!不足的欢迎提问留言. ...
- 深入解读ES6系列(一)
ECMAScript 6(ES6)简介 前言: 哈喽小伙伴们,爱说'废'话的Z又回来了,欢迎来到Super IT曾的博客时间,我说啦这个月要带的福利,说了更的博客肯定不能水你们,要一起进步学习嘛,今天 ...
- 深入解读ES6系列(二)
ES6函数 哈喽小伙伴们,爱说'废'话的Z又回来了,欢迎来到Super IT曾的博客时间,上一节说了es6的历史,变量,以及闭包,这一节我们继续我们知识的海洋,一起奋斗不秃头!不足的欢迎提问留言. 今 ...
- 网络结构解读之inception系列四:Inception V3
网络结构解读之inception系列四:Inception V3 Inception V3根据前面两篇结构的经验和新设计的结构的实验,总结了一套可借鉴的网络结构设计的原则.理解这些原则的背后隐藏的 ...
- React与ES6(四)ES6如何处理React mixins
React与ES6系列: React与ES6(一)开篇介绍 React和ES6(二)ES6的类和ES7的property initializer React与ES6(三)ES6类和方法绑定 React ...
- 大白话,讲编程之《ES6系列连载》汇总
如果你经历过2,3年前的前端开发,你一定感受过兼容IE6,7的痛苦,一定用过网页三剑客的dreamweaver编写html,面试的时候面试官一定会问你:会用PS切图吗? 刚开始的时候你发现,web前端 ...
- [ES6系列-01]Class:面向对象的“新仇旧恨”
[原创]CoderPower 大家好,这里是码路工人有力量,我是码路工人,你们是力量. 这是公众号(码路工人有力量)开通后的第二篇,写得还是有待改进吧.这次准备写一个关于ES6基础的短文系列,努力尽快 ...
- 前端构建大法 Gulp 系列 (四):gulp实战
前端构建大法 Gulp 系列 (一):为什么需要前端构建 前端构建大法 Gulp 系列 (二):为什么选择gulp 前端构建大法 Gulp 系列 (三):gulp的4个API 让你成为gulp专家 前 ...
- Netty4.x中文教程系列(四) 对象传输
Netty4.x中文教程系列(四) 对象传输 我们在使用netty的过程中肯定会遇到传输对象的情况,Netty4通过ObjectEncoder和ObjectDecoder来支持. 首先我们定义一个U ...
随机推荐
- 教妹学Java:Spring 入门篇
你好呀,我是沉默王二,一个和黄家驹一样身高,刘德华一样颜值的程序员(管你信不信呢).从两位偶像的年纪上,你就可以断定我的码龄至少在 10 年以上,但实话实说,我一直坚信自己只有 18 岁,因为我有一颗 ...
- 环境变量之classpath配置和临时配置
前言 本篇文章介绍classpath环境变量的配置和一个环境变量配置的技巧:临时配置path环境变量. 正文 classpath环境变量配置 在上完了"Hello World"这堂 ...
- Java已五年1—二本物理到前端实习生到Java程序员「回忆贴」
关键词:郑州 二本 物理专业 先前端实习生 后Java程序员 更多文章收录在码云仓库:https://gitee.com/bingqilinpeishenme/Java-Tutorials 前言 没有 ...
- Elasticsearch系列---多字段搜索
概要 本篇介绍一下multi_match的best_fields.most_fields和cross_fields三种语法的场景和简单示例. 最佳字段 bool查询采取"more-match ...
- HTML每日学习笔记(1)
7.15.2019 1.HTML脚本——JavaScript的嵌入使用,使 HTML 页面具有更强的动态和交互性. <script> 标签用于定义客户端脚本,比如 JavaScript. ...
- C++之 ostream详细用法
前言 在 C++中,ostream表示输出流,英文”output stream“的简称.在 C++中常见的输出流对象就是标准输出流cout,很少自定义ostream的对象,更多的是直接使用cout.那 ...
- SpringCloud学习系列<一>版本介绍
SpringCloud学习踩坑记<一> SpringCloud版本迭代实在太快,学习起来也是各种坑,博主用的是"当前"的最新版本,借鉴周立老大的Spring Cloud ...
- Swift 4.0 字典(Dictionary)学习
定义字典常量(常量只有读操作) let dictionary1 = ["key1": 888, "key2": 999] let dictionary2: [S ...
- 原创 记录一次线上Mysql慢查询问题排查过程
背景 前段时间收到运维反馈,线上Mysql数据库凌晨时候出现慢查询的报警,并把原始sql发了过来: --去除了业务含义的sql update test_user set a=1 where id=1; ...
- select_related prefetch_related
# select_related与prefetch_related# # select_related帮你直接连表操作 查询数据 括号内只能放外键字段# # res = models.Book.obj ...