javascript语言的执行环境是单线程(single thread),就是指一次只能完成一件任务。若是有多个任务,就必须排队,前面一个任务完成,再执行后面一个任务,以此类推。javascript
这种模式的好处是实现起来比较简单,执行环境相对单纯;可是只要耗时比较多,假若有一个任务耗时很长,后面的任务都必须排队等着,会拖延整个程序的执行。为了解决这个问题,Javascript语言将任务的执行模式分红两种:同步(Synchronous)和异步(Asynchronous)。前端
Javascript处理异步的方法有如下几种:vue
回调是一个函数被做为一个参数传递到另外一个函数里,在那个函数执行完后再执行。回调函数是异步编程最基本的方法,其优势是简单、容易理解和部署;缺点是容易产生回调地狱。java
ajax('XXX1', () => { // callback 函数体 ajax('XXX2', () => { // callback 函数体 ajax('XXX3', () => { // callback 函数体 }) }) })
这就是所谓的回调地狱,回调地狱带来的负面做用有如下几点:webpack
这种方式,异步任务的执行不取决于代码的顺序,而取决于某个事件是否发生。web
1.普通方式ajax
f1.on('done', f2);
上面这行代码的意思是,当f1发生done事件,就执行f2。算法
2.onclick方法npm
element.onclick=function(){ //处理函数 } element.onclick=handler1; element.onclick=handler2; element.onclick=handler3; // 只有handler3会被添加执行
3.addEvenListener编程
elment.addEvenListener("click",handler1,false); elment.addEvenListener("click",handler2,false); elment.addEvenListener("click",handler3,false);
该方法的第三个参数是一个布尔值:当为false时表示由里向外,true表示由外向里。
咱们假定,存在一个"信号中心",某个任务执行完成,就向信号中心"发布"(publish)一个信号,其余任务能够向信号中心"订阅"(subscribe)这个信号,从而知道何时本身能够开始执行。这就叫作"发布/订阅模式"(publish-subscribe pattern)
首先,f2向信号中心jQuery订阅done信号。
jQuery.subscribe('done', f2);
而后,f1进行以下改写:
function f1() { setTimeout(function () { jQuery.publish('done'); }, 1000); }
f1执行完成后,向信号中心jQuery发布done信号,从而引起f2的执行。f2完成执行后,能够取消订阅(unsubscribe)
jQuery.unsubscribe('done', f2);
这种方式的优势:能够经过查看“消息中心”,了解存在多少信号、每一个信号有多少订阅者,从而监控程序的运行。
以上都是ES6以前的异步处理方式。ES6以后出现了promise。它是异步编程的一种解决方案,比传统的解决方案(回调函数)——更合理和更强大。
Promise 对象有如下两个特色。
1.对象的状态不受外界影响。Promise 对象表明一个异步操做,有三种状态:pending
(进行中)、fulfilled
(已成功)和rejected
(已失败)。只有异步操做的结果,能够决定当前是哪种状态,任何其余操做都没法改变这个状态。
2.一旦状态改变,就不会再变,任什么时候候均可以获得这个结果
1.ES6 规定,Promise 对象是一个构造函数,用来生成 Promise 实例。
const promise = new Promise((resolve, reject) => { if (/* 异步操做成功 */){ resolve(success) } else { reject(error) } })
Promise接收一个函数做为参数,函数里有resolve和reject两个参数:
resolve
方法的做用是将Promise
的pending
状态变为fullfilled
,在异步操做成功以后调用,能够将异步返回的结果做为参数传递出去。reject
方法的做用是将Promise
的pending
状态变为rejected
,在异步操做失败以后调用,能够将异步返回的结果做为参数传递出去。2.Promise 实例生成之后,能够用then
方法分别指定resolved
状态和rejected
状态的回调函数。
promise.then((success) => { // 对应于上面的resolve(success)方法 }, (error) => { // 对应于上面的reject(error)方法 } // 还能够写成这样 (推荐使用这种写法) promise.then((success) => { // 对应于上面的resolve(success)方法 }).catch((error) => { // 对应于上面的reject(error)方法 })
then(onfulfilled,onrejected)
方法中有两个参数,两个参数都是函数:
resolve()
方法(即异步成功后的回调方法)reject()
方法(即异步失败后的回调方法)(第二个参数可选)。3.promise构造函数是同步执行的,then方法是异步执行的
const promise = new Promise((resolve, reject) => { console.log(1) resolve() console.log(2) }) promise.then(() => { console.log(3) }) console.log(4) // 1 2 4 3
Promise.finally()
用于指定无论 Promise 对象最后状态如何,都会执行的操做。
promise .then(result => {···}) .catch(error => {···}) .finally(() => {···});
Promise.all()
用于处理多个异步处理,好比说一个页面上须要等多个 ajax 的数据回来才执行相关逻辑。
const p = Promise.all([p1, p2, p3]);
p的状态由p一、p二、p3决定,分红两种状况。
Promse.race()
就是赛跑的意思,Promise.race([p1, p2, p3])里面哪一个结果得到的快,就返回那个结果,无论结果自己是成功状态仍是失败状态。
const p = Promise.race([p1, p2, p3])
上面代码中,只要p一、p二、p3之中有一个实例率先改变状态,p的状态就跟着改变。那个率先改变的 Promise 实例的返回值,就传递给p的回调函数。
async/await是JavaScript为了解决异步问题而提出的一种解决方案,许多人将其称为异步的终极解决方案。async 函数,就是 Generator 函数的语法糖。
相较于 Generator,Async 函数的改进在于下面四点:
1.凡是在前面添加了async的函数在执行后都会自动返回一个Promise对象
async function test() { } let result = test() console.log(result) //即使代码里test函数什么都没返回,咱们依然打出了Promise对象
2.await必须在async函数里使用,不能单独使用
function test() { let result = await Promise.resolve('success') console.log(result) } test() //执行之后会报错
总结移动端H5开发经常使用技巧(干货满满哦!)
从零开始构建一个webpack项目
总结几个webpack打包优化的方法
总结前端性能优化的方法
总结vue知识体系之高级应用篇
总结vue知识体系之实用技巧
几种常见的JS递归算法
封装一个toast和dialog组件并发布到npm
一文读尽前端路由、后端路由、单页面应用、多页面应用
浅谈JavaScript的防抖与节流
关注的个人公众号不按期分享前端知识,与您一块儿进步!