在ajax请求数据的过程当中,咱们能够异步拿到咱们想要的数据,而后在回调中作相应的数据处理。
这样作看上去并无什么麻烦,可是若是这个时候,咱们还须要作另一个ajax请求,这个新的ajax请求的其中一个参数,得从上一个ajax请求中获取,这个时候咱们就须要在回调函数中再写一个异步请求,而后在这个异步函数的回调函数里在写相应的数据处理。要是连续嵌套个三四层,每每就很恶心了。
写起来就像下面这样:javascript
$.ajax({ type:'get', url:'url_1', data: 'data' success : function(res){ //相应的数据处理 var data = res.data $.ajax({ type:'get', url:'url_2', data: data success : function(res){ //相应的数据处理 $.ajax({ type:'get', url:'url_3', data: data success : function(res){ //相应的数据处理 } }) } }) } })
在这种状况下Promise就能发挥它的威力了;html
先不谈语法,下面先来一个实例,创建感性的认识java
<!DOCTYPE html> <html> <head lang="en"> <meta charset="UTF-8"> <title></title> <script src="http://libs.baidu.com/jquery/2.0.0/jquery.js"></script> </head> <body> </body> <script> function a(data){ return new Promise(function(resolve,reject){ console.log("我是从上一个回调函数里传过来的数据",data) ; $.ajax({ type:'post', dataType: 'jsonp', url:'http://api.money.126.net/data/feed/0000001,1399001', //jsonp跨域调用上证与深证的股票指数 data:{ }, success : function(res){ console.log(res) ; resolve(res) ; }, error:function(res){ console.log("Error:") ; console.log(res) ; reject(res) ; } }) }); } function b(data){ return new Promise(function(resolve,reject){ console.log("我是从上一个回调函数里传过来的数据",data) ; $.ajax({ type:'post', dataType: 'jsonp', url:'https://api.douban.com/v2/movie/top250', //跨域调用豆top250的电影 success : function(res){ console.log(res) ; resolve(res) ; }, error:function(res){ console.log("Error:") ; console.log(res) ; reject(res) } }) }); } a().then(b).then(a).then(b).catch(function(a){console.log("final Error:",a)}) ; </script> </html>
打印结果以下所示:
jquery
能够发现,
Promise
经过简单的链式调用就能获得以前多层回调才能达成的效果;并且从代码的结构来看,有效地减少了各个请求之间的耦合;es6
别的不谈,先打印一下 Promise
, console.dir(Promise)
, 看看它到底是哪号人物:ajax
原来
Promise
自己是一个构造函数,本身身上有all
、reject
、resolve
这几个的方法,在其prototype
上有then
、catch
这两个方法。那么用Promise new出来的对象也会有then
、catch
这两个方法。json
一、咱们发现,在 new Promise(function(resolve,reject){})
里传了两个方法 resolve
、 reject
做为参数,这两个方法一般会在函数的回调里被用到。一旦执行到resolve()
或者 reject()
,那么这个函数会中止执行,而后触发后面的 then()
或者 catch()
方法。准确一点来讲,执行到resolve()
会触发 then()
方法,执行到 reject()
会触发 catch()
方法。api
二、resolve
和 reject
方法里能够传入参数 ,就像 resolve(data)
和 reject(data)
。 若是这样作 ,那么在后面的 then()
或者 catch()
里传入一个带参数的函数 , 就像 then(function(data){})
或者 catch(function(data){})
, 就能获得 data
的数据 。跨域
三、说的再专业一些,Promise
对象有三种状态,他们分别是:promise
这三种状态不受外界影响,并且状态只能从 pending
改变为 resolved
或者rejected
,而且不可逆。在 Promise
对象的构造函数中,resolve
和 reject
就是用来处理Promise的状态变化。
通常来讲,调用 resolve
或 reject
之后,Promise 的使命就完成了,后继操做应该放到 then
或者 catch
方法里面,而不该该直接写在 resolve()
或 reject()
的后面 (事实的状况是,resolve()
或 reject()
的后面的代码也不会执行)。
new Promise()
里的函数是马上执行的须要注意的的是,new Promise()
里的函数是马上执行的 ,也就是说 ,当你执行下面这段代码时,就已经开始执行异步请求了:
<script> new Promise(function(resolve,reject){ $.ajax({ type:'post', dataType: 'jsonp', url:'http://api.money.126.net/data/feed/0000001,1399001', data:{ }, success : function(res){ console.log(res) ; resolve(res) ; }, error:function(res){ reject(res) ; } }) }); </script>
这也是为何,在上面第二段的实例中,须要用 a()
和 b()
函数把 new Promise()
给包起来
then()
函数的返回值必定是 Promise
对象还须要注意的的是,then()
函数的返回值必定是 Promise
对象,哪怕手动 return
一个值也无济于事,以下面的代码,照样能运行成功:
a().then(function (){console.log("hello");return 1}).then(b) ;
这也解释了为何咱们能够链式调用 then()
函数。
Promise.all()
与Promise.race()
的用法想要从两个不一样的 ajax
请求里分别得到信息,这两个任务是能够并行执行的,就能够用 Promise.all()
实现:
<script> var p1 = function(){ return new Promise(function (resolve, reject) { setTimeout(resolve, 500, 'P1'); }); } ; var p2 = function(){ return new Promise(function (resolve, reject) { setTimeout(resolve, 1000, 'P2'); }); } ; // 同时执行p1和p2,并在它们都完成后执行then var start = function(){ Promise.all([p1(), p2()]).then(function (results) { console.log(results); // 得到一个Array: ['P1', 'P2'] }); } </script>
有些时候,多个异步任务是为了容错。好比,分别发两个不一样的 ajax
请求读取用户的我的信息,只须要得到先返回的结果便可,这种状况下,就能够用Promise.race()
实现:
<script> var p1 = function(){ return new Promise(function (resolve, reject) { setTimeout(resolve, 500, 'P1'); }); } ; var p2 = function(){ return new Promise(function (resolve, reject) { setTimeout(resolve, 1000, 'P2'); }); } ; var start = function(){ Promise.all([p1(), p2()]).then(function (results) { console.log(results); // 'P1' }); } </script>
因为 p1
执行较快,Promise
的 then()
将得到结果 'P1'
。 p2
仍在继续执行,但执行结果将被丢弃。
若是咱们组合使用Promise,就能够把不少异步任务以并行和串行的方式组合起来执行。