JS进阶 ] 分析JS中的异步操作
写在前面
JS因为是单线程的,所以在执行事务的时候,往往会因为某个事务的延迟,而导致服务器假死,这时候异步编程就显的格外重要,但是异步编程一般理解为回调函数callback,典型的就是node,回调函数的层层嵌套又导致程序过于冗余,因为闭包的存在,导致了内存的泄露或者误改上一层回调函数的参数,于是又有一个疑问,能不能用同步的方式去写异步,ES6的promise就是以同步流程的方式写出异步操做,但是piomise原生操作写起来比较长,能不能简介操作promise,ES7就又出现async/await的概念,与async/await同等语法糖作用的有依赖co库的generator函数,generator函数也是用来解决异步操作,不过得依赖co库,co 函数库是著名程序员 TJ Holowaychuk 于2013年6月发布的一个小工具,用于generator函数的自动执行。
好了,那就罗列出js的异步操作
1、回调函数
ajax典型的异步操作,利用XMLHttpRequest,回调函数获取服务器的数据传给前台
之前也分析过ajax(飞机票)
回调函数的含义就是耗时任务f1中执行f2,f1不会堵塞住,而是先执行f2,再延迟执行f1
2、事件监听
addEventListener
当监听事件发生时,先执行回调函数,再对监听事件进行改写
3、观察者模式,也叫订阅发布模式
多个观察者可以订阅同一个主题,主题对象改变时,主题对象就会通知这个观察者
其中步骤包括,订阅、发布、退订;先订阅(subscribe)一个主题对象,根据主题对象发布(publish)内容,期间也退订(unsubscribe)主题对象,一旦退订就无法再次发布
可以把订阅一个主题对象理解成监听一个事件
观察者模式的一个特点就是一旦主题事件一改变,就会通知整个观察者;观察者模式还可以计算出订阅事件的个数
4、promise
上面也提到了,promise是异步编程的解决方案,是一种容器,保存着异步操作的结果,可以把异步函数以同步函数的形式写出来
promise第一个特点:对象状态不受外界影响,有三个状态pending(),fulfilled(),rejected(),只有异步操作才会更改这个状态,其他操作无法改变这个状态
promise第二个特点:一旦状态改变,pending->fulfilled或pending->rejected,状态就会凝固住,称为resolve,通过promise的回调函数可以立即得到这个结果,与事件监听不同,一旦事件错误,就无法再次监听
promise第三个特点:避免了回调函数的层层嵌套,实际上写promise时,虽然没有回到函数的层层嵌套,但是又有then的嵌套,这个又有新的解决方法
promise第一个缺点:一旦promise建立,就会立即执行,无法中途停止
举个例子,假如去淘宝买东西,去看上一个东西,想要买,已经点击确定购买了,但是你又cancle了,突然你发现工资发了,你又发送一个请求说又要买了,服务器接收到了你的第一个异步请求,你又有异步请求,异步请求又不能停止,求服务器阴影面积?
promise的第二个缺点:promise不设置回调函数,抛出的错误无法在外部捕获
piomise的第三个缺点:处于pending状态,无法知道进展到哪个状态
下面一个经典的案例:用promise写出ajax,就体现了promise的特点
function getJSON(url){
var promise = new Promise(function(resolve,reject){
var xhr = new XMLHttpRequest();
xhr.open("get",url);
xhr.onreadystatechange=ajax;
xhr.responseType = "json";
xhr.setRequestHeader("Accept", "application/json");
xhr.send();
function ajax(response){
if (this.readyState !=4) {
return;
}
if (this.status ==200) {
resolve(this.response)
}else{
reject(new Error(this.status.responseText))
} }
})
return promise;
}
getJSON("/new2").then(function(value){
console.log(value);
},function(error){
console.log(error);
})
5、es7语法糖async/await
async异步函数是promise的完成状态,async函数直接then去获取状态改变值,catch来获取错误
await只允许在async内部使用,就是async异步函数内部想要继续then,就可以采用await异步函数,await异步函数是内部的async异步函数
async极大精简了promise的操作
async function asyncFn(){
return 123;
}
asyncFn()
.then(x => {console.log(x)})
.catch(err => console.log(error))
这是未精简的promise操作,功能是把最终结果return最外层的promise,但是 用到了多层嵌套,比较复杂
const fn = () => {
return getJSON()
.then(data =>{
if(data.params){
return otherGetJSON(data).then(otherdata =>{
console.log(otherdata);
return otherdata;
})
}else{
console.log(data)
}
})
}
而async异步函数,直接去return出结果就行,这就是await是async内部async异步函数
const fn = async () => {
const data = await getJSON();
if(data.params){
const otherdata = await otherGetJSON(data);
console.log(otherdata);
return otherdata;
}else{
console.log(data)
return data;
}
}
6、co库的generator函数
generator函数是一个异步函数,只有异步操作有结果才会交还执行权
generator用到了ES6的遍历Iterator的概念,创建一个指针对象,指向数据结构的起始位置,每次next指向下一个指针结构成员,直至指向的下一个结构成员为undefined
generator概念就是,每次遍历读用next方法,内部指针从结构头部指向下一个结构成员,直至下一个结构成员为undefined,遇到yield或return时会返回value和done参数,value表示yield或return的值,done表示是否结束
function * gen(x){
var y = yield x +2;
return y;
}
var g = gen(1);
console.log(g.next()) // { value: 3, done: false }
console.log(g.next()) // { value: undefined, done: true }
yield是遍历的停止标志
而generator中的yield*表示 yield* 后面跟着一个可遍历的结构
写在后面
最近的review,让我对js又有新的认识,js异步操作是js的核心所在,也是js迷人的地方,async/await和generator都是promise的语法糖,我觉得没有优劣之分,可能道行太浅,还需刷道,希望业界前辈多多指责我,让我进步更快。
好了,今天的交流就结束了,下次复习js定时器的内存分配等。
JS进阶 ] 分析JS中的异步操作的更多相关文章
- js进阶 12-13 jquery中one方法和trigger方法如何使用
js进阶 12-13 jquery中one方法和trigger方法如何使用 一.总结 一句话总结: 1.one()方法和on()方法的区别是什么? 除了one()只执行一次,其它和on()一模一样,包 ...
- js进阶 11-18 jquery中操作选择器的方法有哪些
js进阶 11-18 jquery中操作选择器的方法有哪些 一.总结 一句话总结:add().addBack().end() 1.add()方法是干嘛的,举一例? 将add()方法后选择器选择的jqu ...
- js进阶 11-3 jquery中css属性如何操作
js进阶 11-3 jquery中css属性如何操作 一.总结 一句话总结:通过css()方法 1.attr和css是有交叉的,比如width,两者中都可以设置,那么他们的区别是什么? 其实通俗一点 ...
- js进阶 10-6 jquery中的属性选择器有哪些
js进阶 10-6 jquery中的属性选择器有哪些 一.总结 一句话总结: 1.第一遍能学会么? 一遍是肯定学不会的,要多学几遍,所以想着怎么加快速度,减少学习的遍数 2.属性选择器是干嘛的? 选择 ...
- js进阶 10-5 jquery中的层级选择器有哪些
js进阶 10-5 jquery中的层级选择器有哪些 一.总结 一句话总结: 1.jquery中的层级选择器有哪些? 四种,后代,子代,兄弟,相邻兄弟 2.如何区别jquery中的层级选择器? 记住这 ...
- js进阶 10-4 jquery中基础选择器有哪些
js进阶 10-4 jquery中基础选择器有哪些 一.总结 一句话总结: 1.群组选择器用的符号是什么? 群组选择器,中间是逗号 2.jquery中基础选择器有哪些? 5种,类,id,tag,群组, ...
- js进阶 10-3 jquery中为什么用document.ready方法
js进阶 10-3 jquery中为什么用document.ready方法 一.总结 一句话总结: 1.document.ready和window.onload的区别:用哪个好? document. ...
- js进阶 9-10 html中如何遍历下拉列表
js进阶 9-10 html中单选框和多选框如何遍历下拉列表 一.总结 一句话总结: 1.select元素的options.length可以获取选择长度,然后用options[i]精确定位到选项,用 ...
- js 进阶 10 js选择器大全
js 进阶 10 js选择器大全 一.总结 一句话总结:和css选择器很像 二.JQuery选择器 原生javaScript中,只能使用getELementById().getElementByNam ...
随机推荐
- chart.js使用常见问题
Chart.js是一个简单.面向对象.为设计者和开发者准备的图表绘制工具库. 在使用过程中新手可能会遇到很多问题导致图标无法显示.下面我们来看一下在使用过程中可能会遇到的问题. 刚开始用chart.j ...
- 第一章:pip 安装 tar.gz 结尾的文件 和 .whl 结尾的文件
1. 假如后缀中还有 .tar.gz 的文件通过 pip 命令进行安装步骤. .单击 .tar.gz结尾的文件,并且对文件进行解压,进入到解压目录中,通过python命令进行安装. 命令如下:在dos ...
- Data Volume 之 bind mount - 每天5分钟玩转 Docker 容器技术(39)
storage driver 和 data volume 是容器存放数据的两种方式,上一节我们学习了 storage driver,本节开始讨论 Data Volume. Data Volume 本质 ...
- 设计模式 - 观察者模式(JDK)
定义:观察者模式定义了对象之间的一对多依赖,这样一来,当一个对象改变状态时,它的所有依赖者都会收到通知并自动更新. 对象: 抽象主题角色:每个抽象主题角色都可以有任意数量的观察者.抽象主题提供可 ...
- HttpClient以json形式的参数调用http接口并对返回的json数据进行处理(可以带文件)
1.参数的url就是被调用的地址,map是你要传的参数.参数转成json我使用的是gson方式转换的. 主要使用的jar包有httpclient-4.5.3.jar.httpcore-4.4.6.ja ...
- DotNetCore跨平台~Dockerfile的解释
回到目录 大叔感觉网上对Dockerfile的说明不是很清楚,或者说怎么去用说的不清楚,在vs2017里我们可以去建立自己的Dockerfile文件,然后你的项目可以被生成一个镜像,把它推到仓库之后, ...
- 全网首创ISE入门级教程
转眼间我已经大三了,现在成为了实验室的负责人,对于下一届学生的纳新重任就交到了我的手上,想采取不同的方法暑假尽可能对他们进行一些培训,所以制作了此教程,说实话,在网上还没有找到关于ISE的入门级使用教 ...
- tag上、push上和pull 取Docker 映像
在此之前需要拥有一个docker Hub账户,注册地址:https://hub.docker.com/. Tag.Push Docker映像 使用docker images 获取当前拥有的映像列表,其 ...
- mybaits错误解决:There is no getter for property named 'parentId ' in class 'java.lang.String'
在使用mybaitis传参数的时候,如果仅传入一个类型为String的参数,那么在 xml文件中应该使用_parameter来代替参数名. 比如mapper中如下方法,只有一个String值 publ ...
- [C++ Calculator 项目] 基础运算实现
Calculator V1.1 注:这是C++计算器项目第二部分-运算 [基于初始部分增改而得] 源文件已上传至github 主要问题: Ⅰ.运算实现的问题在于( ) + - * /的优先级的处理,以 ...