為什麼要使用promise

chenhongdong發表於2018-03-28

起因

大家都知道做前端開發的時候最讓人頭痛的就是處理非同步請求的情況,在請求到的成功回撥函式裡繼續寫函式,長此以往形成了回撥地獄。

function load() {
    $.ajax({
        url: 'xxx.com',
        data: 'jsonp',
        success: function(res) {
            init(res, function(res) {
                render(res, function(res) {
                    // 一層一層又一層
                });
            });
        }
    }
}

load();
複製程式碼

這樣的程式碼看層級少了當然還是可以湊合看的,但是多起來的話,那就難以維護了,無論是開發者自身還是同事來接手專案,都是極其無奈的!還要我怎樣,要怎樣,怎樣,樣。

於是乎 出現了Promise

當年在聽到關於Promise的報導的時候沒有太多關注,只是知道是解決回撥地獄問題的,一種非同步請求解決方案而已。 後來在工作當中發現JQ也實現了相關的方法,上程式碼

$.get('xxx.php').done(function() {
    alert('成功的回撥');    // 相當於Promise的resolve()
});
複製程式碼

現在看來,真的和Promise差不多呢。那麼我們回到今天的主角來

先介紹一下Promise的三種狀態:

  • Pending 建立Promise物件時的初始狀態
  • Fulfilled 成功時的狀態
  • Rejected 失敗時的狀態

說完了狀態直接上程式碼,我們得會用才行:

還以上面load函式的例子

  // then方法是用的最多的了
  // 按照then來執行成功和失敗的回撥函式
  function load() {
    return new Promise((resovel, reject) => {
        $.ajax({
            url: 'xxx.com',
            data: 'jsonp',
            success: function(res) {
                resolve(res);
            },
            error: function(err) {
                reject(err);
            }
        });
    });
}

// 用一下
load().then(data => {
    console.log(data);  // 請求到的資料
    console.log('請求資料成功');
}, err => {
    console.log('請求失敗');
});
複製程式碼

除了處理請求,Promise還可以寫在普通的函式中

function init(options) {
    return new Promise((resolve, reject) => {
        if (options.id) {
            console.log('你是唯一')
            resolve(options.id);
        } else {
            console.log('不行,不行');
            reject()
        }
    });
}

init({id: 110})
    .then(id => {
        console.log(id);          // 110
        let obj = {id, nickname: '左夕'};
        return obj;
    })
    .then(other => {
        console.log(other);    // { id: 110, nickname: '左夕' }
    });
複製程式碼

Promise.all和Promise.race有點型別

all是Promise的狀態都為成功才表示成功

race是Promise的狀態是有一個先成功的狀態了,就表示成功

最近很火的axios其實就是呼叫了Promise,寫法也是很相似的

由於它是第三方包,需要npm i axios安裝一下

// 發個get請求
axios.get('user/', {
    id,
    username
}).then(res => {
    console.log(res);   // 成功
}).catch(err => {
    console.log(err);   // 失敗
});

// 再來個post請求
axios.post('login/', {
    username,
    password
}).then(res => {
    console.log(res);   // 成功
}).catch(err => {
    console.log(err);   // 失敗
});

// 也有all的操作
function getUser() {
    return axios.get('/user');
}

function sendMsg() {
    return axios.post('/info', {msg});
}

axios.all([getUser(), sendMsg()]).then(res => {})
複製程式碼

總結一下:Promise常用的就是這些了,then返回的也是一個Promise物件,所以可以繼續呼叫.then方法。有說的不對的地方,還望指出。

那麼接下來呢,就來實現一下Promise吧,用都用了不實現一下,也不夠意思,點這裡

相關文章