不想了解過程,請直接劃到最後.看最終效果
更多內容歡迎訪問個人博客:林除夕javascript
通俗的說就是回調函數嵌套回調函數的問題,以下java
// 聲明一個函數 function foo(data, callback) { data++; callback(data); } // 回調地獄 foo(1, function(data) { foo(data, function(data) { foo(data, function(data){ foo(data, function(data){ foo(data, function(data){ foo(data, function(data){ console.log(data);// 7 }) }) }) }) }); });
怎麼樣是否是很刺激,稍微複雜一點,保證你看到頭暈眼花。ajax
將這種嵌套式
的調用改造爲串聯式
,那麼下面咱們就來看看怎麼解決.json
其中的關鍵方法網絡
表示一個異步操做: 當實例被建立時就表示一個具體異步操做若是不傳入執行函數,那麼它只是在形式上是異步操做,可是沒有任何的異步實操
以下異步
// 建立一個形式上的異步操做 ===> 沒有任何具體的異步操做(例如ajax,jsonp等),咱們知道它是異步操做可是不知道它究竟在操做什麼 var p = new Promise(); // 建立一個實際的異步操做 var p = new Promise(function(){ // 在這裏執行一個異步操做,例如:ajax請求 })
經過.then指定回調函數(包括成功和失敗),以下:函數
// 爲了防止咱們的異步操做函數在Promise實例化過程當中被執行,將其封裝在一個函數中,在對應的時機去使用它 function sendAjax() { // 建立並返回一個包含實際的異步操做的Promise對象 return new Promise(function(resolve,reject) { // 在這裏執行一個異步操做,例如:ajax請求 if('ajax請求出現錯誤') return reject('錯誤內容') resolve('成功以後須要用到的數據或內容') }); } // 接收實例對象 var p = sendAjax() // 經過.then方法指定成功和失敗的回調 p.then(function(data){ // 默認第一個是成功的回調 }, function(err){ // 默認第二個是失敗的回調 })
同執行過程以下: 在異步操做的等待時間內完成後續的處理函數的註冊(由於異步操做受網絡和數據大小的限制通常時間都較長,然後續註冊執行函數由於都是內存內直接操做且數據量很小注冊時間幾乎能夠忽略不計)jsonp
st=>start: 開始 e=>end: 結束 op1=>operation: 調用函數實例化對象 op2=>operation: 發起異步操做請求 op3=>operation: 註冊回調函數p.then op4=>operation: 完成異步請求 op5=>operation: 調用回調函數 op6=>operation: 異步請求是否完成 cont=>condition: yes or no? st->op1->op2->op6->cont cont(no)->op3->op5 cont(yes)->op5->e
注意:code
在調用.then的時候,成功的回調(resolve)是必須的,失敗的回調(reject)能夠不傳遞
// 爲了防止咱們的異步操做函數在Promise實例化過程當中的執行,將其封裝在一個函數中 function sendAjax(data) { // 建立並返回一個包含實際的異步操做的Promise對象 return new Promise(function(resolve,reject) { // 在這裏執行一個異步操做,例如:ajax請求 if('ajax請求出現錯誤') return reject('錯誤內容') resolve('成功以後須要用到的數據或內容') }); } // 接收實例對象 var p = sendAjax(data) // 經過.then方法指定成功和失敗的回調 p.then(function(data){ // 默認第一個是成功的回調 }, function(err){ // 默認第二個是失敗的回調 }) // ======================== // 串聯解決回調地獄問題 sendAjax(data) .then(function(newData1){ // newData就是異步操做獲得的數據或內容 // 這裏用來放成功以後如何處理 // 數據處理完成後若是還須要執行嵌套的相似操做 return sendAjax(newData2) }) .then(function(newData3){ // newData就是異步操做獲得的數據或內容 // 這裏用來放成功以後如何處理 // 數據處理完成後若是還須要執行嵌套的相似操做 return sendAjax(newData4) }) .then.... .then(function(result){ // 結束數據嵌套處理,輸出數據 console.log(result) })
有兩種狀況,一種會阻止後續執行,一種不會對象
sendAjax(data) .then(function(newData1){ // newData就是異步操做獲得的數據或內容 // 這裏用來放成功以後如何處理 // 數據處理完成後若是還須要執行嵌套的相似操做 return sendAjax(newData2) },function(err){ // 在這裏執行一個處理失敗信息的操做 // 處理完成後返回下一個要處理的對象,這樣就不會阻止後續操做 return sendAjax(newData2) }) .then(function(newData3){ // newData就是異步操做獲得的數據或內容 // 這裏用來放成功以後如何處理 // 數據處理完成後若是還須要執行嵌套的相似操做 return sendAjax(newData4) })
sendAjax(data) .then(function(newData1){ // newData就是異步操做獲得的數據或內容 // 這裏用來放成功以後如何處理 // 數據處理完成後若是還須要執行嵌套的相似操做 return sendAjax(newData2) }) .then(function(newData3){ ... }) .catch(function(err){ // 輸出錯誤信息 // 這種方式捕獲異常和錯誤,只要前面任何一個.then出現問題都會終止整個執行鏈,而後拋出異常 })