前言异步编程模式在前端开发过程中越来越重要。从最初的XHR到封装后的Ajax,都是在尝试解决异步编程过程中的问题。随着新的ES6标准的到来,处理异步数据流也有了新的解决方案。我们都知道,在传统的ajax请求中,当异步请求之间的数据之间存在依赖关系时,可能会产生丑陋的多层回调,俗称'回调地狱'(callbackhell),令人望而生畏。Promise的出现让我们告别回调函数,写出更优雅的异步代码。在实践的过程中,我发现Promise并不完美。Async/Await是近年来添加到JavaScript中的最具革命性的特性之一。Async/Await提供了另一种方法使异步代码看起来像同步代码。接下来我们介绍这两种处理异步编程的方案。一、Promise的原理和基本语法1、Promise的原理Promise是一种对异步操作的封装,可以通过一个独立的接口加入,在异步操作成功或失败时执行方法。主流规范是Promises/A+。Promise中有几种状态:pending:初始状态,未完成或被拒绝;fulfilled:运行成功,为了表述方便,将fulfilled换成resolved;拒绝:操作失败。Pending可以转换为fulfilled或rejected,并且只能转换一次,也就是说,如果pending转换为fulfilled状态,则不能再转换为rejected。而fulfilled和rejected状态只能由pending转化而来,两者不能相互转化。2.Promise的基本语法Promise实例必须实现方法then()必须能够接收两个函数作为参数then()必须返回一个Promise实例//如果低版本浏览器不支持Promise,通过cdn这种方式2.Promise多个串行操作Promise可以做更多的事情。比如有几个异步任务,需要先完成任务1。如果成功,则去执行任务2,如果有任何任务失败,则不会继续执行错误处理函数。要串行执行这样的异步任务,没有Promise,就需要写一层层嵌套的代码。使用Promises,我们只需要编写job1.then(job2).then(job3).catch(handleError);其中job1、job2和job3都是Promise对象。例如,我们想在加载第一张图片后加载第二张图片。如果其中一个执行失败,执行报错函数:varsrc1='https://www.imooc.com/static/img/index/logo_new.png'varresult1=loadImg(src1)//result1isaPromiseobjectvarsrc2='https://img1.mukewang.com/545862fe00017c2602200220-100-100.jpg'varresult2=loadImg(src2)//result2是一个Promise对象result1.then(function(img1){console.log('第一张图片加载完成',img1.width)returnresult2//链式操作}).then(function(img2){console.log('第二张图片加载完成',img2.width)}).catch(function(ex){console.log(ex)})这里需要注意的是,同一个promise可以多次调用then方法,并且then方法必须返回一个promise对象。上面的例子中,如果result1.then没有返回一个明文的Promise实例,则默认为自己的Promise实例,即result1,result1.then返回一个result2实例,然后执行.then实际上执行的是result2。然后。三、Promise除string外的常用方法Promise除了可以连续执行多个异步任务外,还可以并行执行异步任务。想象一个页面聊天系统。我们需要从两个不同的URL获取用户的个人信息和好友列表。这两个任务可以并行执行。使用Promise.all()实现以下功能:varp1=newPromise(function(resolve,reject){setTimeout(resolve,500,'P1');});varp2=newPromise(function(resolve,reject){setTimeout(resolve,600,'P2');});//当执行p1和p2时,当它们都完成时then:Promise.all([p1,p2]).then(function(results){console.log(results);//得到一个数组:['P1','P2']});有时,多个异步任务是为了容错。比如同时从两个URL中读取用户的个人信息,只需要先拿到返回的结果即可。在这种情况下,使用Promise.race():varp1=newPromise(function(resolve,reject){setTimeout(resolve,500,'P1');});varp2=newPromise(function(resolve,reject){setTimeout(resolve,600,'P2');});Promise.race([p1,p2]).then(function(result){console.log(result);//'P1'});由于p1执行得更快,Promise的then()将得到结果'P1'。p2继续执行,但是执行结果会被丢弃。总结:Promise.all接受一个promise对象数组,全部完成后,统一执行success;Promise.race接受一个包含多个promise对象的数组,只要有一个完成,就执行成功接下来我们对上面的例子做如下修改,加深对两者的理解:varsrc1='https://www.imooc.com/static/img/index/logo_new.png'varresult1=loadImg(src1)varsrc2='https://img1.mukewang.com/545862fe00017c2602200220-100-100.jpg'varresult2=loadImg(src2)Promise.all([result1,result2]).then(function(datas){console.log('all',datas[0])//
