简析JavaScript异步编程
什么是同步?
要了解什么是异步,首先应该知道同步这个概念
因为JavaScript是单线程的,所谓单线程就是一次只能执行一件任务,只有当前面的任务执行完毕后才会继续执行后续任务,程序的执行顺序和任务的排列顺序是一致的。
同步JavaScript优缺点:
- 优点
实现简单,执行环境单纯,不需要共享资源(不需要锁机制 ),以主线程执行结果为准·
- 缺点
如果一个任务行执行时间较长,后面的任务会被阻塞,影响整个程序的执行
什么是异步?
虽然JavaScript是单线程的,但是其执行的任务被分为同步任务和异步任务两种。
同步任务:
在主线程上排队执行的任务,只有前一个任务执行完毕,才能执行后一个任务;
异步任务:
不进入主线程,而进入"任务队列"(task queue),只有等主线程任务执行完毕,"任务队列"开始通知主线程,请求执行任务,该任务才会进入主线程执行。
这种不断检查然后从任务队列中取出对应的事件放入函数的调用栈中执行被称作事件循环
关于任务队列相关知识看这里 一篇文章快速搞懂JavaScript事件循环、任务队列、同步异步和阻塞非阻塞
为什么要有异步?
有这种异步任务的设计是因为要想从服务器获取某个资源是需要一定的时间的,进行IO操作时,cpu比较空闲,那么完全可以让cpu挂起正在执行的任务,先运行后续的任务,等到IO操作返回结果了,再把挂起的任务执行完毕。
异步带来的问题
因为异步任务会在同步任务全部执行完毕才去执行,假如后面的代码依赖前面返回的内容,这时候就会出错
比如说下面代码想实现发送ajax请求后,控制台输出服务端返回的结果,结果输出undefined
function res (){// get请求var xhr = new XMLHttpRequest();xhr.open('GET', 'http://localhost:5000/jsonp/', true);// xhr.withCredentials = truexhr.send();xhr.onreadystatechange = function (e) {if (xhr.readyState == 4 && xhr.status == 200) {return xhr.responseText}};
}
console.log(res()) //undefined
因为ajax请求为异步任务,会被放进任务队列中,等待同步任务(console.log(res()))执行完毕再执行,所以console.log(res())时打印undefined
所以JavaScript中指的异步编程实际上是指将异步执行的代码,变为同步执行(等待某部分代码执行完毕,再执行另一部分代码)
callback回调函数
最基本的实现异步编程的方法就是callback回调函数,异步callbacks 其实就是正常的函数,只不过是作为参数传递给那些在后台执行的其他函数,当那些后台运行的代码结束,就调用callbacks函数
最常见的callback回调就是事件监听了,为按钮绑定点击事件
btn.addEventListener('click', () => {alert('You clicked me!');
});
事件监听的第一个参数是事件类型,第二个就是回调函数。这里将回调函数作为事件监听addEventListener函数的参数,所以回调函数不会立即执行,事件监听会负责在合适的时候执行回调函数
当然也可以自己写一个包含callback的函数createCallback
// 回调1
function callbackOne (){console.log('我是回调1')
}
// 回调2
function callbackTwo (){console.log('我是回调2')
}creatCallback(doSomething,callbackOne,callbackTwo)
回调函数优点
简单,容易实现
回调函数缺点
不利于代码阅读和维护,各部分之间高度耦合,而且每个任务只能设置一个回调函数,当有多个请求相互依赖的话,很容易出现回调地狱的情况
promise
promise 是一个对象,他被创建时是一个不一定已知的值(简单说就是一个容器,里面保存着某个未来才会结束的事件的结果,通常是一个异步操作),promise会和异步操作最终成功还是失败相关联
then方法分别指定resolved状态和rejected状态的回调函数,当异步操作成功(fulfilled)或者失败(rejected)时相应的回调才会被调用,回调返回的结果也是一个promise对象。
promise对象有三个状态:
- pending:初始状态,操作执行前的状态
- fulfilled:兑现状态,操作成功后的状态
- rejected:拒绝状态,操作失败的状态
当promise对象从初始状态被兑现或者拒绝时,promise的then方法中相关回调将会执行,如果promise在绑定回调时已经是fulfilled状态或者rejected状态,then中回调就会立即执行。
new Promise((resolve, reject) => {//这里console.log操作会和promise状态关联,成功=>fulfilled,失败rejectdeconsole.log('执行完成');resolve('执行成功!');reject('执行失败!')
}).then(rs => {console.log(rs);
}), rj=>{console.log(rj)
};
then中接受两个参数,一个是成功的回调(resolved),一个是失败的回调(rejected)。如果需要连续执行两个或者多个异步操作,我们可以通过创造一个promise链来解决,也就是多次调用then方法,并且每个回调都接收前一个成功操作的结果作为输入。
new Promise((resolve,reject)=>{console.log('promise1')resolve('promise2')
}).then(re=>{console.log(re)return re
}).then(re2=>{console.log(re2)return error // 未定义的变量导致执行失败,promise对象进入rejected状态,catch捕获到错误
}).catch(rj=>{console.log(rj.message)
})
通过catch去捕获异常的好处是链式promise中有一个回调抛出错误后仍然可以继续使用后续操作,不需要马上处理这个错误
async/await
async是es6中解决同步异步问题的一个语法糖本质是基于Promise的异步行为,简单理解就是async声明一个异步函数,然后await后面的代码等待异步操作之后才会执行
async函数可能包含0个或者多个await表达式。await表达式会暂停整个async函数的执行进程并出让其控制权,只有当其等待的基于promise的异步操作被兑现或被拒绝之后才会恢复进程。async/await在多层回调嵌套时书写更加直观
// promise
function submit() {console.log('submit');// 经过俩个校验check1().then(res1=>{check2(res1).then(res2=>{/** 提交请求*/})})
}
submit();// async/await
async function asyncSubmit() {let res1 = await check1();let res2 = await check2(res1);console.log(res1, res2);/** 提交请求*/
}
使用async / await关键字就可以在异步代码中使用普通的try / catch代码块。
async function test() {try {await new Promise(function (resolve, reject) {throw new Error('产生差错了');});} catch(e) {console.log('err', e)}return await('成功了');
}
简析JavaScript异步编程相关推荐
- JavaScript 异步编程--Generator函数、async、await
JavaScript 异步编程–Generator函数 Generator(生成器)是ES6标准引入的新的数据类型,其最大的特点就是可以交出函数的执行的控制权,即:通过yield关键字标明需要暂停的语 ...
- 写给初学者的JavaScript异步编程和背后思想
导读: 对于接触JavaScript这门编程语言没有多久的本菜鸡而言,在相当长的一段时间内,我都完全无法理解这门语言中的异步编程,不明白什么叫异步编程以及为什么需要异步编程.为什么顺序执行程序就不行了 ...
- Javascript异步编程之一异步原理
本系列的例子主要针对node.js环境,但浏览器端的原理应该也是类似的. 本人也是Javascript新手,把自己这段时间学习积累的要点总结下来,希望可以对同样在学习Javascript/node.j ...
- 网页javascript加载不出_写给初学者的JavaScript异步编程和背后思想
导读:对于接触JavaScript这门编程语言没有多久的本菜鸡而言,在相当长的一段时间内,我都完全无法理解这门语言中的异步编程,不明白什么叫异步编程以及为什么需要异步编程.为什么顺序执行程序就不行了呢 ...
- JavaScript异步编程【下】 -- Generator、Async/await
文章内容输出来源:拉勾教育 大前端高薪训练营 前言 在JavaScript异步编程[上]和 JavaScript异步编程[中]中,我们已经讲到了处理异步编程的两种方法:回调函数 和 Promise. ...
- JavaScript异步编程【上】 -- 同步和异步、事件循环(EventLoop)、微任务和宏任务、回调函数
文章内容输出来源:拉勾教育 大前端高薪训练营 前言 在我们学习JavaScript中,我们知道,JavaScript的执行环境是单线程的.所谓单线程是指一次只能完成一个任务,如果有多个任务,就必须排队 ...
- JavaScript异步编程原理
众所周知,JavaScript 的执行环境是单线程的,所谓的单线程就是一次只能完成一个任务,其任务的调度方式就是排队,这就和火车站洗手间门口的等待一样,前面的那个人没有搞定,你就只能站在后面排队等着. ...
- 【学习笔记】Part1·JavaScript·深度剖析-函数式编程与 JS 异步编程、手写 Promise(二、JavaScript 异步编程)
[学习笔记]Part1·JavaScript·深度剖析-函数式编程与 JS 异步编程.手写 Promise(课前准备) [学习笔记]Part1·JavaScript·深度剖析-函数式编程与 JS 异步 ...
- JavaScript异步编程
JavaScript异步编程 一.概述 1.单线程模型 2.同步任务和异步任务 3.任务队列和事件循环 4.异步操作的模式 回调函数 事件监听 发布/订阅 5.异步操作的流程控制 串行执行 并行执行 ...
最新文章
- DataSet RecordSet 互转
- 使用CATT作批量数据导入
- 学会Python真的有高收入?「python笔记」Python对象
- 深入实践Spring Boot2.4.3 节点实体持久化
- MongoDB与Tokyo Tyrant性能比较(2):并发写入操作
- [已解决] org.hibernate.AnnotationException:未为实体类指定标识符
- LINUX编译automake
- 微信点击右上角 在浏览器中打开代码
- 少儿编程scratch系统介绍(附网站源码)
- 电气工程学计算机有用吗,我是学计算机的,因为一直喜欢电气,所以想考个注..._电气工程师_帮考网...
- 龙之谷手游微信连接授权服务器失败,龙之谷手游ios微信授权失败怎么办_龙之谷手游ios微信授权失败解决办法-66街机网...
- linux服务器关机日期,linux服务器last查看关机记录
- Matlab超声影像智能硬件
- 酷派7296刷机包 高仿IOS美化 细节精仿
- WXML和HTML的区别
- Handle Protocol
- 从软件本质的角度看待软件危机
- 阿里云率先达成国家绿色数据中心标准,平均PUE低于1.3...
- Struts2 拦截器中实现对数据进行数据库操作
- 6个关键步骤,手把手教你构建图模型
热门文章
- 数据结构——堆栈——计算器的原理(中缀变后缀)
- tcp长连接判断对方断开的方法
- java面试官看到这些面试答案只会点头:过了过了,明天直接上班
- Excel数据导入速度太慢
- python竖着展示诗_Python把一段字符串用“右起竖排”的古文格式输出
- 用Hadoop中MapReduce进行TopN排序
- 三年Android开发快手、美团、支付宝连挂,android基础视频教程
- View‘s SELECT contains a subquery in the FROM clause
- Json的序列化和反序列化的几种方式
- 铜陵学院计算机大赛,体验过程,收获成长——2018年中国大学生计算机设计大赛参赛后记...