前端为什么有的接口明明是成功回调却执行了.catch失败回调_Web前端:ES6是干什么的?(下)...
大家好,我来了!本期为大家带来的Web前端学习知识是”Web前端:ES6是干什么的?(下)“,喜欢Web前端的小伙伴,一起看看吧!
主要内容
- Promise
- Generator
- Async
- Class
- Extends
- proxy
学习目标
第一节 Promise
1.1 promise是什么?
Promise 是异步编程的一种解决方案,比传统的解决方案——回调函数和事件——更合理和更强大
有了Promise对象,就可以将异步操作以同步操作的流程表达出来,避免了层层嵌套的回调函数
1.2 promsie产生的原因
在JavaScript的世界中,所有代码都是单线程执行的。
由于这个“缺陷”,导致JavaScript的所有网络操作,浏览器事件,都必须是异步执行。异步执行可以用回调函数实现:
function callback() {console.log('Done');
}
console.log('before setTimeout()');
setTimeout(callback, 1000); // 1秒钟后调用callback函数
console.log('after setTimeout()');
观察上述代码执行,在Chrome的控制台输出可以看到:
before setTimeout()
after setTimeout()
(等待1秒后)
Done
可见,异步操作会在将来的某个时间点触发一个函数调用。
异步回调的问题:
- 之前处理异步是通过纯粹的回调函数的形式进行处理
- 很容易进入到回调地狱中,剥夺了函数return的能力
- 问题可以解决,但是难以读懂,维护困难
- 稍有不慎就会踏入回调地狱 - 嵌套层次深,不好维护
回调地狱
一般情况我们一次性调用API就可以完成请求。
有些情况需要多次调用服务器API,就会形成一个链式调用,比如为了完成一个功能,我们需要调用API1、API2、API3,依次按照顺序进行调用,这个时候就会出现回调地狱的问题
1.3 promise详解
1.3.1 语法
new Promise(function (resolve, reject) {// 一段耗时的异步操作resolve('成功') // 数据处理完成// reject('失败') // 数据处理出错}).then((res) => {console.log(res)}, // 成功(err) => {console.log(err)} // 失败)
resolve作用是,将Promise对象的状态从“未完成”变为“成功”(即从 pending 变为 resolved),在异步操作成功时调用,并将异步操作的结果,作为参数传递出去;
reject作用是,将Promise对象的状态从“未完成”变为“失败”(即从 pending 变为 rejected),在异步操作失败时调用,并将异步操作报出的错误,作为参数传递出去。
【代码演示】
请求网络接口:
图片懒加载
1.3.2 promise有三个状态:
1、pending[待定]初始状态
2、fulfilled[实现]操作成功
3、rejected[被否决]操作失败
当promise状态发生改变,就会触发then()里的响应函数处理后续步骤;
promise状态一经改变,不会再变。
Promise对象的状态改变,只有两种可能:
从pending变为fulfilled
从pending变为rejected。
这两种情况只要发生,状态就凝固了,不会再变了。
1.4 promise案例
回调包装成Promise,他有两个显而易见的好处:
1、可读性好
2、返回 的结果可以加入任何Promise队列
实战示例,回调地狱和promise对比:
1.4.1 传统写法
/***第一步:找到北京的id第二步:根据北京的id -> 找到北京公司的id第三步:根据北京公司的id -> 找到北京公司的详情目的:模拟链式调用、回调地狱***/// 回调地狱// 请求第一个API: 地址在北京的公司的id$.ajax({url: 'https://www.easy-mock.com/mock/5a52256ad408383e0e3868d7/lagou/city',success (resCity) {let findCityId = resCity.filter(item => {if (item.id == 'c1') {return item}})[0].id$.ajax({// 请求第二个API: 根据上一个返回的在北京公司的id “findCityId”,找到北京公司的
第一家公司的idurl: 'https://www.easy-mock.com/mock/5a52256ad408383e0e3868d7/lagou/position-list',success (resPosition) {let findPostionId = resPosition.filter(item => {if(item.cityId == findCityId) {return item}})[0].id// 请求第三个API: 根据上一个API的id(findPostionId)找到具体公司,然后返回公司详情$.ajax({url: 'https://www.easy-mock.com/mock/5a52256ad408383e0e3868d7/lagou/company',success (resCom) {let comInfo = resCom.filter(item => {if (findPostionId == item.id) {return item}})[0]console.log(comInfo)}})}})}})
1.4.2 Promise
onst cityList = new Promise((resolve, reject) => {$.ajax({url: 'https://www.easy-mock.com/mock/5a52256ad408383e0e3868d7/lagou/city',success (res) {resolve(res)}})})// 第二步:找到城市是北京的idcityList.then(res => {let findCityId = res.filter(item => {if (item.id == 'c1') {return item}})[0].idfindCompanyId().then(res => {// 第三步(2):根据北京的id -> 找到北京公司的idlet findPostionId = res.filter(item => {if(item.cityId == findCityId) {return item}})[0].id// 第四步(2):传入公司的idcompanyInfo(findPostionId)})})// 第三步(1):根据北京的id -> 找到北京公司的idfunction findCompanyId () {let aaa = new Promise((resolve, reject) => {$.ajax({url: 'https://www.easy-mock.com/mock/5a52256ad408383e0e3868d7/lagou/position-list',success (res) {resolve(res)}})})return aaa}// 第四步:根据上一个API的id(findPostionId)找到具体公司,然后返回公司详情function companyInfo (id) {let companyList = new Promise((resolve, reject) => {$.ajax({url: 'https://www.easy-mock.com/mock/5a52256ad408383e0e3868d7/lagou/company',success (res) {let comInfo = res.filter(item => {if (id == item.id) {return item}})[0]console.log(comInfo)}})})}
本章作业
Promise是什么 如何使用
第二节Generator
Generator 函数是 ES6 提供的一种异步编程解决方案,语法行为与传统函数完全不同
2.1 Generator语法
形式上,Generator 函数是一个普通函数,但是有两个特征。一是,function关键字与函数名之间有一个星号;二是,函数体内部使用yield表达式,定义不同的内部状态(yield在英语里的意思就是“产出”)。
function* getData() {yield http();yield getLog();
}// Generator函数function* generator() {yield 'status one' // yield 表达式是暂停执行的标记 return 'hello world'}let iterator = generator() // 调用 Generator函数,函数并没有执行,返回的是一个Iterator对象iterator.next() // {value: "status one", done: false},value 表示返回值,
done 表示遍历还没有结束iterator.next() // {value: "hello world", done: true},value 表示返回值,
done 表示遍历结束
yield 表达式
由于 Generator 函数返回的遍历器对象,只有调用next方法才会遍历下一个内部状态,所以其实提供了一种可以暂停执行的函数。yield表达式就是暂停标志。
遍历器对象的next方法的运行逻辑如下。
(1)遇到yield表达式,就暂停执行后面的操作,并将紧跟在yield后面的那个表达式的值,作为返回的对象的value属性值。
(2)下一次调用next方法时,再继续往下执行,直到遇到下一个yield表达式。
(3)如果没有再遇到新的yield表达式,就一直运行到函数结束,直到return语句为止,并将return语句后面的表达式的值,作为返回的对象的value属性值。
function* getData() {yield http();yield getLog();
}
function getLog() {console.log("我是网络请求");
}
function http() {return $.ajax({type: "get",url: "http://iwenwiki.com/api/blueberrypai/getIndexChating.php",success: function (data) {console.log(data);}})
}var gd = getData();
gd.next();
gd.next();
2.2 async
ES2017 标准引入了 async 函数,使得异步操作变得更加方便。
async 函数是什么?一句话,它就是 Generator 函数的语法糖
function getLog(result,ms) {console.log(result);// 页面渲染函数$("#root").append(`<img src='${ result.titleImg }' />`);return new Promise((resolve) => {setTimeout(resolve, ms);});
}function Hello() {console.log("我是最后执行");
}function http() {return $.ajax({type: "get",url: "http://iwenwiki.com/api/blueberrypai/getIndexChating.php",success: function (data) {console.log("网络请求执行完成");}})
}async function getData() {var result = await http();await getLog(result,2000);Hello();
}
getData();
本章作业
Generator 函数
第三节 模块的导入导出
在es5中,用module.exports和exports导出模块,用require引入模块。
es6新增export和export default导出模块,import导入模块。
3.1名字导出(name export)
名字导出可以在模块中导出多个声明。
export
export后必须跟语句, 何为语句, 如声明, for, if 等都是语句, export 不能导出匿名函数, 也不能导出某个已经声明的变量, 如:
export const bar = function() {}; // 合法
export bar; // 非法
export 1; // 非法
export function foo () {}; // 合法, 后跟的是声明语句
export { foo }; // 合法, 后面跟的{}理解为语句, 就像if后面的{}一样
export { foo as bar }; // 合法export { foo: foo }; // 非法, 后面的{}被解析成对象
3.2 默认导出(default export)
一个模块只能有一个默认导出,对于默认导出,导入的名称可以和导出的名称不一致,这对于导出匿名函数或类非常有用。
3.2.1 export default
export default在整个模块中只能出现一次, 后只能具体的值, 何为具体的值, 如1, 2, 3, 再比如一个函数声明(非表达式), 或者是一个类声明(与函数声明一个意思), 或者匿名函数, 只要是能用变量接受的都可以, 例子:
export default 1; // 合法
export default function foo() {}; // 合法, 因为function foo() {}
能被变量接受, 如 var bar = function foo() {}
export default const bar = 1; // 非法, 因为var a = const bar = 1 是不合法的
export default { foo }; // 合法, {} 被理解为一个对象
export default { foo: foo }; // 合法, 同上
3.2.2 import
import语法为:
import { x, y } from './test.js';import * as some from './test.js'; // 命名空间导入
import './test.js';import { default as test } from './test.js';
导入再导出
export { some } from './test.js';export * from './test.js';
导入后跟需要导入的绑定和模块说明符, 导入绑定的列表并非对象的解构, 二者并无关联, 导入的标识符很像const声明的变量, 不可更改, 也同时存在暂时性死区, 如有理解错误的地方还请不吝指教
第四节Class类
传统的javascript中只有对象,没有类的概念。它是基于原型的面向对象语言。原型对象特点就是将自身的属性共享给新对象。这样的写法相对于其它传统面向对象语言来讲,很有一种独树一帜的感脚!非常容易让人困惑!
如果要生成一个对象实例,需要先定义一个构造函数,然后通过new操作符来完成。构造函数示例:
- 当使用了构造函数,并且new 构造函数(),后台会隐式执行new Object()创建对象;
- 将构造函数的作用域给新对象,(即new Object()创建出的对象),而函数体内的this就代表new Object()出来的对象
- 执行构造函数的代码。
- 返回新对象(后台直接返回);
4.1 类的定义
ES6引入了Class(类)这个概念,通过class关键字可以定义类。该关键字的出现使得其在对象写法上更加清晰,更像是一种面向对象的语言。如果将之前的代码改为ES6的写法就会是这个样子:
注意项
1.在类中声明方法的时候,千万不要给该方法加上function关键字
2.方法之间不要用逗号分隔,否则会报错
由下面代码可以看出类实质上就是一个函数。类自身指向的就是构造函数。所以可以认为ES6中的类其实就是构造函数的另外一种写法!
console.log(typeof Person);//function
console.log(Person===Person.prototype.constructor);//true
以下代码说明构造函数的prototype属性,在ES6的类中依然存在着。
console.log(Person.prototype);//输出的结果是一个对象
实际上类的所有方法都定义在类的prototype属性上。代码证明下:
当然也可以通过prototype属性对类添加方法。如下:
还可以通过Object.assign方法来为对象动态增加方法
constructor方法是类的构造函数的默认方法,通过new命令生成对象实例时,自动调用该方法。
constructor方法如果没有显式定义,会隐式生成一个constructor方法。所以即使你没有添加构造函数,构造函数也是存在的。constructor方法默认返回实例对象this,但是也可以指定constructor方法返回一个全新的对象,让返回的实例对象不是该类的实例。
constructor中定义的属性可以称为实例属性(即定义在this对象上),constructor外声明的属性都是定义在原型上的,可以称为原型属性(即定义在class上)。hasOwnProperty()函数用于判断属性是否是实例属性。其结果是一个布尔值, true说明是实例属性,false说明不是实例属性。in操作符会在通过对象能够访问给定属性时返回true,无论该属性存在于实例中还是原型中。
类的所有实例共享一个原型对象,它们的原型都是Person.prototype,所以proto属性是相等的
由此,也可以通过proto来为类增加方法。使用实例的proto属性改写原型,会改变Class的原始定义,影响到所有实例,所以不推荐使用!
class不存在变量提升,所以需要先定义再使用。因为ES6不会把类的声明提升到代码头部,但是ES5就不一样,ES5存在变量提升,可以先使用,然后再定义。
4.2 Class 的继承
Class 可以通过extends关键字实现继承,这比 ES5 的通过修改原型链实现继承,要清晰和方便很多。
4.3 proxy
proxy在目标对象的外层搭建了一层拦截,外界对目标对象的某些操作,必须通过这层拦截
var proxy = new Proxy(target, handler);
new Proxy()表示生成一个Proxy实例,target参数表示所要拦截的目标对象,handler参数也是一个对象,用来定制拦截行为
· targetWithLog 读取属性的值时,实际上执行的是 logHandler.get :在控制台输出信息,并且读取被代理对象 target 的属性。
· 在 targetWithLog 设置属性值时,实际上执行的是 logHandler.set :在控制台输出信息,并且设置被代理对象 target 的属性的值
4.4 Proxy的作用
对于代理模式 Proxy 的作用主要体现在三个方面
- 拦截和监视外部对对象的访问
- 降低函数或类的复杂度
- 在复杂操作前对操作进行校验或对所需资源进行管理
代码演示:
本期为大家带来的Web前端学习知识”Web前端:ES6是干什么的?(下)“介绍完毕了,想了解更多内容的小伙伴,关注我,更多内容等你看,我们下期再见!
前端为什么有的接口明明是成功回调却执行了.catch失败回调_Web前端:ES6是干什么的?(下)...相关推荐
- 前端为什么有的接口明明是成功回调却执行了.catch失败回调_前端进阶高薪必看-手写源码篇(高频技术点)...
前言 此系列作为笔者之前发过的前端高频面试整理的补充 会比较偏向中高前端面试问题 当然大家都是从新手一路走过来的 感兴趣的朋友们都可以看哈 初衷 我相信不少同学面试的时候最怕的一个环节就是手写代码 大 ...
- 前端为什么有的接口明明是成功回调却执行了.catch失败回调_前端知识整理
css 异步编程: 传统的异步解决方案采用回调函数和事件监听的方式 新方案: ES6的新语法Promise promise就是一个容器,里面包含着一个未来才会结束的事件(通常是一个异步操作)的结果.比 ...
- webstorm前端调用后端接口_软件测试面试题:怎么去判断一个bug是前端问题还是后端问题...
大家好,在软件测试面试过程中,经常有面试官问到这个问题,那我们应该如何回答才好呢?少废话,直接看答案: 答案: 在页面上发现bug之后,要想判断这个问题属于后端还是前端,我就需要来判断这个页面背后调用 ...
- H5的jsapi微信支付:wx.chooseWXPay,ios手机在支付成功后不执行success中的回调函数
对于iOS客户端支付成功后不进入chooseWXPay函数success的问题原因是:目前没有得到解答 临时解决方案: 支付成功后,安卓和iOS的返回都是{"errMsg":&qu ...
- 前端中怎么把网页多个文件夹的内容整合成一个_web前端学习笔记
web前端的定义:是面向用户(浏览者)的互联网技术统称.主要包括Web界面的结构.Web界面的外观视觉表现以及Web界面的交互实现. HTML结构语言:超文本标记语言. Web前端的分类:前端设计和前 ...
- Nginx解决前端调用后端接口跨域问题
Nginx解决前端调用后端接口跨域问题 参考文章: (1)Nginx解决前端调用后端接口跨域问题 (2)https://www.cnblogs.com/wangymd/p/11200746.html ...
- 前端与后端接口的交互案例
一.案例描述 1,前端页面提供用户名,密码输入框. 2,通过Ajax发送请求到后端Serlvet. 3,后端Serlvet处理请求,根据输入的用户名和密码返回给前端不同信息 前端访问后端接口通过后端提 ...
- Java回调网址_极光短信- 回调接口 - 极光文档
回调接口 设置并校验回调地址: 回调消息格式说明: 测试回调功能的方法: 设置回调地址 功能说明 设置并校验回调地址 操作路径 Step1:登入控制台 Step2:进入应用模版 Step3:右侧菜单中 ...
- App前端及后端接口,模拟数据及返回值
App前端及后端接口,模拟数据 :接口文档 目录 1. 全局状态码 6 2. 前台 7 2.1. 首页 7 2.1.1. 商品分类列表接口 7 2.1.2. 展示轮播图接口 9 2.1.3. 展示广告 ...
最新文章
- ZBar与ZXing使用后感觉
- 标准功能模块组件 -- 内部联络单组件,内部邮件组件,提高多人异地协同办公效率...
- Linux Shell 只列出目录的方法
- OpenStack在dashboard界面点击管理员网络,服务器页面出错
- php学习---环境搭建安装 编译器的安装
- c++ 数组换行_C语言的数组的构建与打印
- Servlet获取URL地址
- 如何写好接口(php写app移动端接口示例)
- 二叉树,建树,前序,中序,后序,递归 非递归
- android 屏幕管理软件,Android Screencast下载
- node.js安装express(零起点搭建本地测试服务器)- 教程篇
- 潭州课堂25班:Ph201805201 第十二课 new方法,定制属性访问,描述符与装饰器 (课堂笔记)...
- Yarn分布式集群操作系统
- 【数学建模】基于matlab GUI干线交通控制方法【含Matlab源码 1259期】
- 【源码】VB6聊天机器人
- 美信科技监控易:智慧高校一体化综合监控解决方案
- 编程方式实现Excel转为JPG/PDF等格式
- 【语音识别】基于HMM实现中文语音识别含Matlab源码
- 《菊与刀》读后感作文5000字
- 苹果各版本手机更换电池的视频
热门文章
- 动态规划求解序列问题(LIS、JLIS)
- Symfony常用指令(收藏版)
- JTable调整列宽
- 对新手的忠告:拒绝创意,回归基础
- 使用studio2005写单元测试
- boot mybatis mysql_SpringBoot+Mybatis+MySql学习
- mysql数据库上传ftp服务器中_备份部分mysql表并上传至指定ftp服务器目录中
- linux shell 变量 管道,linux下shell,变量,管道,重定向等基础知识及技巧
- 定时任务scheduleAtFixedRate设定每天某个时刻执行
- python中的列表分片详解_python列表与元组详解实例