jQuery.ajax()實質上就是在ajax的基礎上進行了封裝,將參數設置,方法調用,數據傳輸,響應的回調函數等都封裝到一個對象中,而後使用這個對象做爲jQurey.ajax()的參數調用實現統一配置執行的效果。css
jQuery.ajax(object)中的object的經常使用屬性及設置:html
1.Easy Mock模擬jQuery.ajax()請求:ajax
1 $.ajax({ 2 url:'https://easy-mock.com/mock/5c0b4a876162b83fe0a50cb9/person', 3 type:"GET", 4 success:function(res){ 5 $.each(res.data,function(index,ele){ 6 console.log(ele); 7 }) 8 }, 9 error:function(e){ 10 if(e.status == 404){ 11 console.log("我找不到主人要的寶貝。。。哇嗚。。。"); 12 } 13 }, 14 complete:function(){ 15 console.log("我完成了任務,快誇我,誇個人人都長得好。"); 16 } 17 });
2.使用context改變函數執行的上下文示例:json
1 //html 2 <div class="wrapper"></div> 3 //js 4 $.ajax({ 5 url:'https://easy-mock.com/mock/5c0b4a876162b83fe0a50cb9/person', 6 type:"GET", 7 success:function(res){ 8 console.log(this);////init [div.wrapper, prevObject: init(1), context: document, selector: ".wrapper"] 9 }, 10 context:$('.wrapper'), 11 complete:function(){ 12 console.log(this)//init [div.wrapper, prevObject: init(1), context: document, selector: ".wrapper"] 13 } 14 });
經過第一部分的分析,好像jQuery.ajax已經所有學會了,no...promise
對於一個簡單的網絡請求來講,第一部分無可厚非已經足以,可是在實際開發中,複雜的需求伴隨着的是複雜的代碼結構和網絡狀況,若是存在多個網絡請求嵌套請求的狀況,代碼會出現死亡三角的複雜區域,對於後期維護會形成很是大的麻煩。爲了更友好的開發維護,jQuery.ajax提供了強大的解決方案,就是jQuery.ajax請求會返回一個Deferred.promise()方法,這個方法提供了友好的ajax不一樣完成狀態的回調函數的添加接口。可能到這裏你還不知道我在說什麼,接下來看下面這個需求的由ajax產生的死亡三角和其解決方案的兩份代碼你就明白了,因爲篇幅比較大,我將需求和死亡三角代碼摺疊,提供最後優雅的代碼展現:服務器
1 <!-- 1、基礎說明 2 code/ code爲0時表示正常狀態,msg爲Ok 3 msg / code爲非0時表示異常狀態,msg爲error 4 data/ 接口返回實體數據 5 2、實體對象 6 power: 7 名稱 / 類型/ 備註 8 Power/ String/ 權限 9 movieList: 10 名稱 / 類型 / 備註 11 name / String/ 電影名字 12 poster/ String/ 電影封面 13 id / String/ 電影id 14 movieInfo: 15 名稱 / 類型 / 備註 16 name / String / 電影名字 17 poster / String / 電影封面 18 direct / String / 導演 19 screewriter/ Array<string>/ 編劇 20 mainActior / Array<string>/ 主演 21 gut / String / 劇情 22 3、接口文檔 23 1.權限 24 BaseUrl:https://easy-mock.com/mock/5c09f40d3c098813c612cce6/movie 25 URL:/power 26 Type:POST 27 Request: 28 名稱 / 類型 / 備註 29 Username/ String/ 用戶名 30 Password/ String/ 密碼 31 Response: 32 { 33 code:0 34 msg:OK 35 data:power 36 } 37 38 2.電影列表 39 BaseUrl:https://easy-mock.com/mock/5c09f40d3c098813c612cce6/movie 40 URL:/movieList 41 Type:GET 42 Response: 43 { 44 code:0 45 msg:OK 46 data:Array <movieList> 47 } 48 49 3.電影詳情 50 BaseUrl:https://easy-mock.com/mock/5c09f40d3c098813c612cce6/movie 51 URL:/movieInfo 52 Type:GET 53 Request: 54 名稱 / 類型 / 備註 55 movieId/ Number/ 電影的ID 56 Response: 57 { 58 code:0 59 msg:OK 60 data:movieInfo 61 }
1 <style type="text/css" media="screen"> 2 *{ 3 padding: 0px; 4 margin: 0px auto; 5 } 6 .tpl{ 7 display: none; 8 } 9 .wrapper{ 10 overflow: hidden; 11 border: 2px solid black; 12 width: 600px; 13 margin: 100px auto 0px; 14 } 15 .movieSection{ 16 float: left; 17 width: 180px; 18 height: 180px; 19 padding: 10px; 20 } 21 .movieSection img{ 22 width: 100%; 23 height: 150px; 24 cursor: pointer; 25 } 26 .movieSection h3{ 27 height: 30px; 28 } 29 </style> 30 <div class="wrapper"> 31 <div class="tpl"> 32 <img src=""> 33 <h3 class="movieName"></h3> 34 </div> 35 </div> 36 <script> 37 // 38 $.ajax({ 39 url:'https://easy-mock.com/mock/5c09f40d3c098813c612cce6/movie/power', 40 type:"POST", 41 data:{ 42 username:"cst", 43 password:"123123" 44 }, 45 success:function(res){ 46 if(res.data.power == 'root'){ 47 //vip 網絡地址發送請求 48 $.ajax({ 49 url:'https://easy-mock.com/mock/5c09f40d3c098813c612cce6/movie/movieList', 50 type:'GET', 51 success:function(res){ 52 var data = res.data; 53 var $Wrapper = $('.wrapper'); 54 $.each(data,function(index,ele){ 55 // ele.name ele.poste 56 var $MovieSection = $('.tpl').clone().removeClass('tpl').addClass('movieSection'); 57 $MovieSection.data({id:ele.id}).on('click',function(){ 58 $.ajax({ 59 url:"https://easy-mock.com/mock/5c09f40d3c098813c612cce6/movie/movieInfo", 60 type:'GET', 61 data:{ 62 movieId:$(this).data('id') 63 }, 64 success:function(res){ 65 var data = res.data; 66 var direct = data.direct; 67 var gut = data.gut; 68 var mainActor = data.mainActor; 69 var screenWriter = data.screenwriter; 70 var htmlStr = '<div class="mask">\ 71 <p>導演:'+ direct +'</p>\ 72 <p>主演:'+ mainActor.reduce(function(prev,curv){ 73 prev += curv + " "; 74 return prev; 75 }) +'</p>\ 76 <p>編劇:'+ screenWriter.reduce(function(prev,curv){ 77 prev += curv + " "; 78 return prev; 79 }) +'</p>\ 80 <p>劇情:'+ gut +'</p>\ 81 </div>'; 82 console.log(htmlStr); 83 $(htmlStr).appendTo('body') 84 .css({position:'absolute',left:$(window).outerWidth()/2,bottom:100,width:400,marginLeft:-200,top:505}); 85 } 86 }); 87 }).children() 88 .eq(0).attr('src',ele.poster) 89 .next().text(ele.name); 90 $Wrapper.append($MovieSection); 91 }); 92 } 93 }); 94 }else{ 95 //非vip 96 } 97 } 98 }); 99 </script>
經過上面的【回調地獄】就有一個值得思考的問題了,如何避免這種代碼帶來的負面影響呢?能夠參考另外一篇博客:jQuery使用():Deferred有狀態的回調列表(含源碼)若是要完整的解析整個jQuery.ajax解決這種【回調地獄】的問題就至關於要將jQuery.Deferred的實現機制所有解析一篇,因此這裏就再也不贅述了。用最簡單的描述就是當經過jQuery.ajax()建立一個請求時,jQuery.ajax()會返回一個jQuery.Deferred對象,更準確的說是會返回Deferred.promise對象,這樣就能夠經過在外部接收這個對象,promise對象上包含了一系列的異步狀態的回調函數的註冊方法done、fail、progress、then。這些方法的具體使用參考前面那篇博客,下面我經過then方法來改造上面那段【回調地獄】的代碼:網絡
1 $.ajax({ 2 url:'https://easy-mock.com/mock/5c09f40d3c098813c612cce6/movie/power', 3 type:"POST", 4 data:{ 5 username:"cst", 6 password:"123123" 7 } 8 //請求會員資源--電影列表 9 }).then(function(res){ 10 if(res.data.power == 'root'){ 11 //vip 網絡地址發送請求 12 return $.ajax({ 13 url:'https://easy-mock.com/mock/5c09f40d3c098813c612cce6/movie/movieList', 14 type:'GET' 15 }); 16 } 17 // 18 }).then(function(res){ 19 var data = res.data; 20 var $Wrapper = $('.wrapper'); 21 var df = $.Deferred(); 22 $.each(data,function(index,ele){ 23 // ele.name ele.poste 24 var $MovieSection = $('.tpl').clone().removeClass('tpl').addClass('movieSection'); 25 $MovieSection.data({id:ele.id}) 26 .on('click',function(){ 27 df.resolve($(this)); 28 }) 29 .children() 30 .eq(0).attr('src',ele.poster) 31 .next().text(ele.name); 32 $Wrapper.append($MovieSection); 33 }); 34 return df.promise(); 35 }).then(function(dom){ 36 return $.ajax({ 37 url:"https://easy-mock.com/mock/5c09f40d3c098813c612cce6/movie/movieInfo", 38 type:'GET', 39 data:{ 40 movieId:dom.data('id') 41 } 42 }) 43 }).then(function(res){ 44 console.log(res); 45 var data = res.data; 46 var direct = data.direct; 47 var gut = data.gut; 48 var mainActor = data.mainActor; 49 var screenWriter = data.screenwriter; 50 var htmlStr = '<div class="mask">\ 51 <p>導演:'+ direct +'</p>\ 52 <p>主演:'+ mainActor.reduce(function(prev,curv){ 53 prev += curv + " "; 54 return prev; 55 }) +'</p>\ 56 <p>編劇:'+ screenWriter.reduce(function(prev,curv){ 57 prev += curv + " "; 58 return prev; 59 }) +'</p>\ 60 <p>劇情:'+ gut +'</p>\ 61 </div>'; 62 console.log(htmlStr); 63 $(htmlStr).appendTo('body') 64 .css({position:'absolute',left:$(window).outerWidth()/2,bottom:100,width:400,marginLeft:-200,top:505}); 65 });
上面改造後的代碼也就是開發中須要遵循的單一職責原則。app