異步發展流程 —— Promise 的基本使用

在這裏插入圖片描述


閱讀原文


Promise 簡介

Promise 是 ES6 的新特性,提供了對 js 異步編程控制的新的解決方案,在過去書寫異步代碼時要靠回調函數,當異步操做依賴於其餘異步操做的返回值時,會出現一種現象,被程序員們稱爲 「回調地獄」,即多層回調函數嵌套,這種代碼的可讀性、維護性都不好,所以誕生了 Promise,固然 Promise 並非徹底擺脫回調,而只是改變了傳遞迴調的位置,大大減小了回調函數嵌套。程序員

<br/>編程

Promise 的使用

一、實例方法 then

Promise 中的代碼默認是同步執行的,then 方法中的回調在微任務隊列中執行,在 Promise 的 then 方法中支持傳入兩個參數,一個是成功的回調,一個是失敗的回調,在 Promise 中調用了 resolve 方法,就會在 then 中執行成功的回調,調用了 reject 方法,就會在 then 中執行失敗的回調,成功的回調和失敗的回調只能執行一個,resolvereject 方法調用時傳入的參數會傳遞給 then 方法中對應的回調函數。數組

// 執行 resolve
let p = new Promise((resolve, reject) => {
    console.log(1);
    resovle(3);
});

console.log(2);

p.then(data => {
    console.log(data);
}, err => {
    console.log(err);
});

// 1
// 2
// 3
// 執行 reject
let p = new Promise((resolve, reject) => {
    reject();
});

p.then(() => {
    console.log(1);
}, () => {
    console.log(2);
});

// 2

若是 Promise 中發生錯誤,就會在 then 中執行失敗的回調。異步

// 失敗的回調
let p = new Primise((resolve, reject) => {
    throw new Error();
});

p.then(() => {
    console.log(1);
}, () => {
    console.log("報錯啦");
});

// 報錯啦

當同一個 Promise 實例的 then 方法屢次調用時,就會屢次執行。異步編程

// 屢次調用 then
let p = new Promise((resolve, reject) => {
    resolve("成功");
});

p.then(data => {
    console.log(data);
});

p.then(data => {
    console.log(data);
});

// 成功
// 成功

二、Promise 的鏈式調用

Promise 支持鏈式調用,每次調用一次 then 方法都會返回一個新的 Promise實例,若是該 then 方法中執行的回調函數有返回值,而且這個返回值會做爲返回的下一個 Promise 實例的 then 方法回調的參數,若是 then 方法的返回值是一個 Promise 實例,那就返回一個新的 Promise 實例,將 then 返回的 Promise 實例執行後的結果做爲返回 Promise 實例回調的參數。函數

// 鏈式調用 then
function read(url) {
    return new Promise((resolve, reject) => {
        fs.readFile(url, "utf8", (err, data) => {
            if (err) reject(err);
            resolve(data);
        })
    });
}

read("1.txt").then(data => {
    // 假設此時讀到的內容爲 Hello world
    return data;
}, err => {
    console.log(err);
}).then(data => {
    console.log(data);
    // Hello world
}, err => {
    console.log(err);
});

read("1.txt").then(data => {
    // 假如此時讀到的 1.txt 的內容爲 2.txt 的字符串,2.txt 的內容爲 Hello world
    return read(data);
}, err => {
    console.log(err);
}).then(data => {
    console.log(data);
    // Hello world
}, err => {
    console.log(err);
});

在 Promise 實例的 then 中若是有錯誤產生,在返回的新的 Promise 實例中的 then 方法中會執行錯誤的回調。this

// 鏈式調用 then 出錯
let p = new Promise((resolve, reject) => {
    resolve();
});

p.then(() => {
    console.log("success", 1);
    throw new Error();
}, () => {
    console.log("error", 1);
}).then(() => {
    console.log("success", 2);
}, () => {
    console.log("error", 2)
})

// success 1
// error 2

在 Promise 中有三個狀態:url

  • pending:等待態
  • fulfilled:成功態
  • rejected:失敗態

Promise 實例的狀態只能從 pendingfulfilled 或從 pendingrejected,狀態一旦發生變化就不可逆,因此 Promise 實現鏈式調用與 jQuery 不一樣,返回的不是 this,只能是一個新的 Promise。spa

三、實例方法 catch

在 Promise 中實例的 catch 方法能夠捕獲鏈式調用中的異常,不須要每次調用 then 方法中都傳入錯誤的回調,在鏈式調用的過程當中只要有任何一個 then 中出現錯誤,都會被 catch 方法捕獲到。code

// catch 方法
let p = new Promise((resolve, reject) => {
    resolve();
});

p.then(() => {
    throw new Error();
    console.log("success", 1);
}).then(() => {
    console.log("success", 2);
}).catch(() => {
    console.log('出錯了');
});

// 出錯了

p.then(() => {
    console.log("success", 1);
}).then(() => {
    throw new Error();
    console.log("success", 2);
}).catch(() => {
    console.log('出錯了');
});

// success 1
// 出錯了

四、靜態方法 Promise.all

Promise 中的靜態方法 all 能夠實現多個 Promise 實例的並行,當全部結果都爲成功時,返回一個數組,該數組存儲的爲每個 Promise 實例的返回結果,每個 Promise 實例的返回順序前後不固定,可是返回值的數組內存儲每個 Promise 的返回值的結果按照最初傳入的順序排列,all 方法的返回值爲一個新的 Promise 實例,返回的數組做爲返回新 Promise 的 then 方法成功回調的參數。

all 傳入的參數數組中的 Promise 實例執行時,只要有一個失敗,則直接返回該 Promise 實例失敗的結果或錯誤信息。

// Promise.all 方法
let p1 = new Promise((resolve, reject) => {
    resolve(1);
});

let p2 = new Promise((resolve, reject) => {
    resolve(2);
});

Promise.all([p1, p2]).then(data => {
    console.log(data);
});

// [1, 2]
// Promise.all 錯誤捕獲
let p1 = new Promise((resolve, reject) => {
    resolve(1);
});

let p2 = new Promise((resolve, reject) => {
    reject(2);
});

Promise.all([p1, p2]).then(data => {
    console.log(data);
}).catch(err => {
    console.log(err);
});

// 2

五、靜態方法 Promise.race

Promise 的靜態方法 race 的用法和 all 相似,參數同爲一個存儲 Promise 實例的數組,返回值一樣是一個新的 Promise 的實例,不一樣的是,數組中的 Promise 實例只有一個結果爲成功,那就直接返回這個結果(只取出最快返回的結果),在沒有成功的結果以前有一個出錯,就直接返回這個錯誤。

// Promise.race 方法
let p1 = new Promise((resolve, reject) => {
    setTimeout(() => resolve(1), 2000);
});

let p2 = new Promise((resolve, reject) => {
    setTimeout(() => resolve(2), 1000);

});

Promise.race([p1, p2]).then(data => {
    console.log(data);
}).catch(err => {
    console.log(err);
});

// 2
// Promise.race 錯誤捕獲
let p1 = new Promise((resolve, reject) => {
    setTimeout(() => reject(1), 1000);
});

let p2 = new Promise((resolve, reject) => {
    setTimeout(() => resolve(2), 2000);

});

Promise.race([p1, p2]).then(data => {
    console.log(data);
}).catch(err => {
    console.log(err);
});

// 1

六、靜態方法 Promise.resolve

Promise 的靜態方法 resolve 能夠直接將 Promise 的狀態變爲成功並返回一個新的 Promise 實例,resolve 的參數會傳遞給返回的新 Promise 實例 then 中成功回調。

// Promise.resolve 方法
Promise.resolve('hello').then(data => {
    console.log(data);
});

// hello

七、靜態方法 Promise.reject

Promise 的靜態方法 rejectresolve 使用徹底相同,都返回一個新的 Promise 實例,不一樣的是 reject 的參數會傳遞給新 Promise 實例的 then 方法失敗回調。

// Promise.reject 方法
Promise.reject('出錯了').then(null, err => {
    console.log(err);
});

// 出錯了

當成功的回調不傳遞時,可使用 null 代替,由於 null 做爲參數會被忽略掉,將參數穿透到下一個 then 的回調中。

相關文章
相關標籤/搜索