C-JavaScript-03:使用ES6中的新特性Promise解決回調地獄問題


不想了解過程,請直接劃到最後.看最終效果

更多內容歡迎訪問我的博客:林除夕

什麼是回調地獄

通俗的說就是回調函數嵌套回調函數的問題,如下

// 聲明一個函數
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
                    })
                })
            })
        })
    });
});

怎麼樣是不是很刺激,稍微複雜一點,保證你看到頭暈眼花。

解決回調地獄的基本思路


將這種嵌套式的調用改造爲串聯式,那麼下面我們就來看看怎麼解決.

解決辦法===>Promise


1.什麼是Promise

  1. **是一個構造函數:**我們通過輸出window對象得到相關信息

  2. 其中的關鍵方法

    • then: 用來指定接下來要執行的函數(成功的回調函數,失敗的回調函數)
    • **resolve: **成功之後的回調函數 ===> 必須要傳的
    • reject: 失敗的回調函數 ===> 不是必須傳的
  3. 表示一個異步操作: 當實例被創建時就表示一個具體異步操作如果不傳入執行函數,那麼它只是在形式上是異步操作,但是沒有任何的異步實操如下

    // 創建一個形式上的異步操作 ===> 沒有任何具體的異步操作(例如ajax,jsonp等),我們知道它是異步操作但是不知道它究竟在操作什麼
    var p = new Promise();
    
    // 創建一個實際的異步操作
    var p = new Promise(function(){
        // 在這裏執行一個異步操作,例如:ajax請求
    })
    
  4. 實例被創建時,傳入的函數會被立即執行: 所以一般都先將實例化過程封裝在函數中,這樣才能在需要的時候再執行

2.如何使用

  1. 通過.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){
        // 默認第二個是失敗的回調
    })
    
  2. 同執行過程如下: 在異步操作的等待時間內完成後續的處理函數的註冊(因爲異步操作受網絡和數據大小的限制一般時間都較長,而後續註冊執行函數因爲都是內存內直接操作且數據量很小注冊時間幾乎可以忽略不計)

    操作流程圖

3.最終效果

注意:

在調用.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)
    })

4.捕獲異常或錯誤

有兩種情況,一種會阻止後續執行,一種不會

  1. 不阻止後續執行的捕獲,提供一個失敗的回調函數
sendAjax(data)
    .then(function(newData1){
    	// newData就是異步操作得到的數據或內容
    	// 這裏用來放成功之後如何處理

    	// 數據處理完成後如果還需要執行嵌套的類似操作
    	return sendAjax(newData2)
	},function(err){
    	// 在這裏執行一個處理失敗信息的操作
    
    	// 處理完成後返回下一個要處理的對象,這樣就不會阻止後續操作
    	return sendAjax(newData2)
	})
    .then(function(newData3){
        // newData就是異步操作得到的數據或內容
        // 這裏用來放成功之後如何處理

        // 數據處理完成後如果還需要執行嵌套的類似操作
        return sendAjax(newData4)
	})
  1. 阻止後續執行的捕獲
sendAjax(data)
    .then(function(newData1){
    	// newData就是異步操作得到的數據或內容
    	// 這裏用來放成功之後如何處理

    	// 數據處理完成後如果還需要執行嵌套的類似操作
    	return sendAjax(newData2)
	})
    .then(function(newData3){
        ...
	})
    .catch(function(err){
        // 輸出錯誤信息
        // 這種方式捕獲異常和錯誤,只要前面任何一個.then出現問題都會終止整個執行鏈,然後拋出異常
    })
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章