promise
在es5中,处理异步采用的是回调机制,比如定时器、DOM事件处理程序、ajax异步请求等;但是回调机制容易造成"回调地狱",以及当逻辑多时代码不易维护;比如:
// 定时器 setTimeout(function(){ // DOM事件处理程序 document.addEventListener('click',function(){ // ajax异步请求 Ajax('http://...',function(res){ }); }); },1000)
很容易看出,回调机制问题所在:
1.代码横向书写,形成金字塔形式;造成“回调地狱”
2.如果每个异步中有很多业务需要处理,就会造成代码不易维护
因此,在ES6中引入了Promise机制来解决异步问题;( jQuery早在1.5版本时就实现了类似的机制 ); 关于异步处理机制,大致上分成三个阶段:
1.回调机制
2.promise (ES6)
3.async / await (ES7中会实现)
异步处理机制Promise
Promise 是个构造函数,需要通过new 出一个对象;先看看Promise这个函数对象上的方法:
// 原型上的方法 Promise.prototype.catch() Promise.prototype.then() // Promise函数对象上的方法 Promise.resolve() Promise.reject() Promise.all() Promise.race()
Promise机制一般使用步骤如下:
var pro = new Promise(function(resolve,reject){ if(...){ resolve(res); // 成功时执行 panding->fulfiled }else{ reject(err); // 失败时执行 panding->rejected } }) pro.then( function(res){}, // 对应 resolve function(err){} // 对应 reject )
明确几点:
1. Promise构造函数参数是个函数,这个函数的参数是resolve,reject;成功时,调用resolve,对应执行then()中的函数;反之,调用reject,执行then()中的第二个函数;
2. Promise对象存在三种状态:pending(初始状态),fulfiled(成功并完成),rejected(失败并完成);执行resolve时,pending->fulfiled;执行reject时,pending->rejected;
3. then函数执行后,返回的仍然是Promise对象,因此可以实现"链式"书写,使得代码由 横向--->纵向;
现在举个例子,改写回调地狱:
// 定时器,回调地狱 // 不难看出,如果每个回调中的逻辑很多,代码将变得不易维护 setTimeout(function(){ console.log(1) setTimeout(function(){ console.log(2) setTimeout(function(){ console.log(3) },3000) },2000) },1000) // 使用Promise改写 var pro = function(ms){ return new Promise(function(resolve,reject){ setTimeout(resolve,ms) }) }; pro(1000) .then(function(){ console.log(1) return pro(2000); }) .then(function(){ console.log(2) return pro(3000); }) .then(function(){ console.log(3) }) // 采用Promise方式,就变得非常舒服 // 纵向书写,顺序执行,基本符合人脑的思维方式:同步阻塞 // 避免了回调地狱,同时代码很容易维护
Promise.prototype.catch()
Promise函数对象有两个核心函数:then() ,catch() ;then()上文中已经阐述过,现在来看catch();
catch()是捕获错误的,当异步不管报什么错,都会被catch()捕获;不管在哪个then()后面,一旦报错,进入catch(),将停止执行;
同时,catch()返回的仍是Promise对象;
var pro = new Promise(function(resolve,reject){ if(...){ resolve(res); // 成功时执行 panding->fulfiled } }) pro.then( function(res){ console.log(ss)// ss 没有定义,将会报错 }, // 对应 resolve ) .catch(function(err){ })
如果在then()中报错,catch则会捕获这个错误;
Promise.all() && Promise.race()
这两个函数在Promise函数对象上,用于执行多个Promise对象;这两个函数的参数都是多个Promise对象,区别如下:
1.all()函数中,只有所有的Promise对象pending-->fulfiled时,才会执行then()中的resolve,参数为数组,对应all()中的Promise对象数组
2.race “竞争”;第一个pending-->fulfiled的Promise对象,率先执行then()中的resolve,参数为第一个执行的返回参数;
感悟:如果熟悉jQuery的延迟对象,ES6中的Promise机制不难理解、掌握;